OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.6/] [rtl/] [sys_gen/] [tst_fx2loop/] [tst_fx2loop.c] - Blame information for rev 24

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 22 wfjm
/* $Id: tst_fx2loop.c 530 2013-08-09 21:25:04Z mueller $ */
2 17 wfjm
/*
3 22 wfjm
 * Copyright 2011-2013 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4 17 wfjm
 *
5
 * This program is free software; you may redistribute and/or modify it under
6
 * the terms of the GNU General Public License as published by the Free
7
 * Software Foundation, either version 2, or at your option any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful, but
10
 * WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
11
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
 * for complete details.
13
 *
14
 *
15
 * Revision History:
16
 * Date         Rev Version  Comment
17 22 wfjm
 * 2013-08-09   530   2.1.2  -read: write up to 9 nstead of 7 words
18 17 wfjm
 * 2012-04-09   461   2.1.1  fix loop back code: fix run-down, add pipe drain
19
 * 2012-03-24   460   2.1    add message loop back code (preliminary)
20
 * 2012-03-10   459   2.0    re-write for asynchronous libusb interface
21
 * 2012-02-12   457   1.1    redo argument handling; add -stat and -rndm
22
 * 2012-01-15   453   1.0.1  add -tx2blast; fix bug in loop read loop
23
 * 2011-12-29   446   1.0    Initial version (only -read/write/loop)
24
*/
25
 
26
#include <stdlib.h>
27
#include <stdio.h>
28
#include <unistd.h>
29
#include <string.h>
30
#include <limits.h>
31
#include <signal.h>
32
#include <poll.h>
33
#include <errno.h>
34
#include <sys/timerfd.h>
35
 
36
#include <libusb-1.0/libusb.h>
37
 
38
static int nsigint = 0;
39
static int endpoll = 0;
40
static libusb_context*       pUsbContext = 0;
41
static libusb_device**       pUsbDevList = 0;
42
static int                   UsbDevCount = 0;
43
static libusb_device_handle* pUsbDevHdl  = 0;
44
 
45
static struct pollfd pollfd_fds[16];
46
static int pollfd_nfds = 0;
47
 
48
struct dsc_queue {
49
  int par_nfrm;
50
  int par_nque;
51
  double stat_nbuf;
52
  double stat_nbyt;
53
  double stat_npt;
54
  uint16_t cval;
55
};
56
 
57
static struct dsc_queue dsc_rx;
58
static struct dsc_queue dsc_tx1;
59
static struct dsc_queue dsc_tx2;
60
 
61
static int par_nwmsg  = 0;
62
static int par_nwrndm = 0;
63
static int par_stat   = 0;
64
static int par_trace  = 0;
65
static int par_nsec   = 0;
66
 
67
static int cur_nwmsg = 0;
68
static double stat_nmsg = 0.;
69
 
70
static double t_start;
71
static int nreq = 0;
72
 
73
static char** argv;
74
static int argc;
75
static int argi;
76
 
77
 
78
void usage(FILE* of);
79
int get_pint(char* p);
80
double get_double(char* p);
81
int get_arg_pint(int min, int max, const char* text);
82
 
83
void do_write(uint16_t* buf, int nw);
84
void do_read(int ep);
85
void do_run();
86
void do_stat();
87
void usb_claim();
88
void usb_release();
89
char* usb_strerror(int rc);
90
void prt_time(void);
91
double get_time(void);
92
void bad_syscall_exit(const char* text, int rc);
93
void bad_usbcall_exit(const char* text, int rc);
94
void bad_transfer_exit(struct libusb_transfer *t, const char* text);
95
 
96
void sigint_handler(int signum)
97
{
98
  printf("\n");
99
  nsigint += 1;
100
  if (nsigint > 3) {
101
    fprintf(stderr, "tst_fx2loop-F: 3rd ^C, aborting\n");
102
    exit(EXIT_FAILURE);
103
  }
104
  return;
105
}
106
 
107
int main(int main_argc, char *main_argv[])
108
{
109
  argc = main_argc;
110
  argv = main_argv;
111
  argi = 1;
112
 
113
  int i;
114
 
115
  /* setup ^C handler */
116
  struct sigaction new_action;
117
 
118
  new_action.sa_handler = sigint_handler;
119
  sigemptyset (&new_action.sa_mask);
120
  new_action.sa_flags = 0;
121
  sigaction (SIGINT, &new_action, NULL);
122
 
123
  /* capture -help case here */
124
  for (i = 1; i < argc; i++) {
125
    if (strcmp(argv[i], "-help") == 0) {
126
      usage(stdout);
127
      return EXIT_SUCCESS;
128
    }
129
  }
130
 
131
  /* determine usb device path (first arg or from RETRO_FX2_VID/PID */
132
  char devbuf[10];
133
  char* path = 0;
134
 
135
  if (argc > argi && argv[argi][0] != '-') {
136
    path = argv[argi];
137
    argi += 1;
138
  } else {
139
    char* env_vid = getenv("RETRO_FX2_VID");
140
    char* env_pid = getenv("RETRO_FX2_PID");
141
    if (env_vid && strlen(env_vid) == 4 &&
142
        env_pid && strlen(env_pid) == 4) {
143
      strncpy(devbuf  , env_vid,4);
144
      devbuf[4] = ':';
145
      strncpy(devbuf+5, env_pid,4);
146
      devbuf[9] = 0;
147
      path = devbuf;
148
    } else {
149
      fprintf(stderr,
150
              "tst_fx2loop-F: RETRO_FX2_VID/PID not or ill defined\n");
151
      return EXIT_FAILURE;
152
    }
153
  }
154
 
155
  /* init libusb, connect to device */
156
  libusb_init(&pUsbContext);
157
  libusb_set_debug(pUsbContext, 3);
158
  UsbDevCount = libusb_get_device_list(pUsbContext, &pUsbDevList);
159
 
160
  libusb_device* mydev = 0;
161
 
162
  if (strlen(path)==8 && path[0]=='/' && path[4]=='/') {
163
    char busnam[4];
164
    char devnam[4];
165
    strncpy(busnam, path+1, 3);
166
    strncpy(devnam, path+5, 3);
167
    busnam[3] = 0;
168
    devnam[3] = 0;
169
 
170
    char* endptr;
171
    uint8_t busnum = strtol(busnam, &endptr, 10);
172
    uint8_t devnum = strtol(devnam, &endptr, 10);
173
 
174
    int idev;
175
    for (idev=0; idev<UsbDevCount; idev++) {
176
      libusb_device* udev = pUsbDevList[idev];
177
      if (libusb_get_bus_number(udev) == busnum &&
178
          libusb_get_device_address(udev) == devnum) {
179
        mydev = udev;
180
      }
181
    }
182
 
183
  } else if (strlen(path)==9 && path[4]==':') {
184
    char vennam[5];
185
    char pronam[5];
186
    memcpy(vennam, path,   4);
187
    memcpy(pronam, path+5, 4);
188
    vennam[4] = 0;
189
    pronam[4] = 0;
190
 
191
    char* endptr;
192
    uint16_t vennum = strtol(vennam, &endptr, 16);
193
    uint16_t pronum = strtol(pronam, &endptr, 16);
194
 
195
    int idev;
196
    for (idev=0; idev<UsbDevCount; idev++) {
197
      libusb_device* udev = pUsbDevList[idev];
198
      struct libusb_device_descriptor devdsc;
199
      libusb_get_device_descriptor(udev, &devdsc);
200
      if (devdsc.idVendor==vennum && devdsc.idProduct==pronum) {
201
        mydev = udev;
202
      }
203
    }
204
 
205
  } else {
206
    fprintf(stderr, "tst_fx2loop-F: dev not in /bus/dev or vend:prod form\n");
207
    return EXIT_FAILURE;
208
  }
209
 
210
  if (mydev == 0) {
211
    fprintf(stderr, "tst_fx2loop-F: no usb device %s found\n", path);
212
    return EXIT_FAILURE;
213
  }
214
 
215
  int rc;
216
  rc = libusb_open(mydev, &pUsbDevHdl);
217
  if (rc) {
218
    fprintf(stderr, "tst_fx2loop-F: failed to open %s rc=%d: %s\n",
219
            path, rc, usb_strerror(rc));
220
    return EXIT_FAILURE;
221
  }
222
 
223
  /* check for internal timeout handling support */
224
  if (libusb_pollfds_handle_timeouts(pUsbContext) == 0) {
225
    fprintf(stderr, "tst_fx2loop-F: libusb_pollfds_handle_timeouts == 0\n"
226
                    "   this program will not run on this legacy system\n");
227
    return EXIT_FAILURE;
228
  }
229
 
230
  for (; argi < argc; ) {
231
 
232
    /* handle setup options ----------------------------------------------- */
233
    if (strcmp(argv[argi],"-nbrx") == 0) {
234
      argi += 1;
235
      dsc_rx.par_nfrm = get_arg_pint(1, 256, "rx buffer size invalid");
236
    } else if (strcmp(argv[argi],"-nqrx") == 0) {
237
      argi += 1;
238
      dsc_rx.par_nque = get_arg_pint(1, 8, "rx buffer count invalid");
239
 
240
    } else if (strcmp(argv[argi],"-nbtx") == 0) {
241
      argi += 1;
242
      dsc_tx1.par_nfrm = get_arg_pint(1, 256, "tx1 buffer size invalid");
243
    } else if (strcmp(argv[argi],"-nqtx") == 0) {
244
      argi += 1;
245
      dsc_tx1.par_nque = get_arg_pint(1, 8, "tx1 buffer count invalid");
246
 
247
    } else if (strcmp(argv[argi],"-nbtx2") == 0) {
248
      argi += 1;
249
      dsc_tx2.par_nfrm = get_arg_pint(1, 256, "tx2 buffer size invalid");
250
    } else if (strcmp(argv[argi],"-nqtx2") == 0) {
251
      argi += 1;
252
      dsc_tx2.par_nque = get_arg_pint(1, 8, "tx2 buffer count invalid");
253
 
254
    } else if (strcmp(argv[argi],"-nwmsg") == 0) {
255
      argi += 1;
256
      par_nwmsg = get_arg_pint(1, 4096, "loopback message size invalid");
257
 
258
    } else if (strcmp(argv[argi],"-rndm") == 0) {
259
      argi += 1;
260
      par_nwrndm = 1;
261
    } else if (strcmp(argv[argi],"-stat") == 0) {
262
      argi += 1;
263
      par_stat = 1;
264
    } else if (strcmp(argv[argi],"-trace") == 0) {
265
      argi += 1;
266
      par_trace = 1;
267
 
268
    /* handle action options ---------------------------------------------- */
269
    } else if (strcmp(argv[argi],"-write") == 0) {
270
      uint16_t buf[4096];
271
      int  nw = 0;
272
      argi += 1;
273
      while(argi < argc && nw < 4096) {
274
        char *argp = argv[argi];
275
        if (argp[0] == '-') break;
276
        char* endptr;
277
        long val = strtol(argp, &endptr, 0);
278
        if ((endptr && endptr[0]) || val < 0 || val > 0xffff) {
279
          nw = 0;
280
          break;
281
        }
282
        argi += 1;
283
        buf[nw++] = (uint16_t)val;
284
      }
285
      if (nw == 0) {
286
        fprintf(stderr, "tst_fx2loop-E: bad word list\n");
287
        break;
288
      }
289
      do_write(buf, nw);
290
 
291
    } else if (strcmp(argv[argi],"-read") == 0) {
292
      argi += 1;
293
      int ep = 6;
294
      if (argi < argc) ep = get_pint(argv[argi++]);
295
      if (ep != 6 && ep != 8) {
296
        fprintf(stderr, "tst_fx2loop-F: bad read endpoint (must be 6 or 8)\n");
297
        return EXIT_FAILURE;
298
      }
299
      do_read(ep);
300
 
301
    } else if (strcmp(argv[argi],"-run") == 0) {
302
      argi += 1;
303
      if (argi < argc) par_nsec = get_pint(argv[argi++]);
304
      if (par_nsec < 0) {
305
        fprintf(stderr, "tst_fx2loop-E: bad args for -run\n");
306
        break;
307
      }
308
      do_run();
309
      do_stat();
310
 
311
    } else {
312
      fprintf(stderr, "tst_fx2loop-F: unknown option %s\n", argv[argi]);
313
      usage(stderr);
314
      return EXIT_FAILURE;
315
    }
316
  }
317
 
318
  return EXIT_SUCCESS;
319
}
320
 
321
/*--------------------------------------------------------------------------*/
322
void usage(FILE* of)
323
{
324
  fprintf(of, "Usage:  tst_fx2loop [dev] [setup-opts...] [action-opts...]\n");
325
  fprintf(of, "  arguments:\n");
326
  fprintf(of, "    dev        path usb device, either bus/dev or vend:prod\n");
327
  fprintf(of, "                 default is $RETRO_FX2_VID:$RETRO_FX2_VID\n");
328
  fprintf(of, "  setup options:\n");
329
  fprintf(of, "    -nbrx nb   buffer size (in 512B) for rxblast\n");
330
  fprintf(of, "    -nqrx nb   number of buffers for rxblast\n");
331
  fprintf(of, "    -nbtx nb   buffer size (in 512B) for txblast or loop\n");
332
  fprintf(of, "    -nqtx nb   number of buffers for txblast or loop\n");
333
  fprintf(of, "    -nbtx2 nb  buffer size (in 512B) for tx2blast\n");
334
  fprintf(of, "    -nqtx2 nb  number of buffers for tx2blast\n");
335
  fprintf(of, "    -nwmsg nw  number words for loop test\n");
336
  fprintf(of, "    -rndm      use random length for loop test\n");
337
  fprintf(of, "    -stat      print live stats\n");
338
  fprintf(of, "    -trace     trace usb calls\n");
339
  fprintf(of, "  action options:\n");
340
  fprintf(of, "    -write w0 w1 ...  write list of words to endpoint 4\n");
341
  fprintf(of, "    -read ep   read from endpoint ep\n");
342
  fprintf(of, "    -run ns    run tests for nw seconds\n");
343
}
344
 
345
/*--------------------------------------------------------------------------*/
346
 
347
int get_pint(char* p)
348
{
349
  char *endptr;
350
  long num = 0;
351
 
352
  num = strtol(p, &endptr, 0);
353
  if ((endptr && *endptr) || num < 0 || num > INT_MAX) {
354
    fprintf(stderr, "tst_fx2loop-E: \"%s\" not a non-negative integer\n", p);
355
    return -1;
356
  }
357
  return num;
358
}
359
 
360
/*--------------------------------------------------------------------------*/
361
 
362
double get_double(char* p)
363
{
364
  char *endptr;
365
  double num = 0.;
366
 
367
  num = strtod(p, &endptr);
368
  if ((endptr && *endptr) || num < 0.) {
369
    fprintf(stderr, "tst_fx2loop-E: \"%s\" not a valid positive float\n", p);
370
    return -1.;
371
  }
372
  return num;
373
}
374
 
375
/*--------------------------------------------------------------------------*/
376
 
377
int get_arg_pint(int min, int max, const char* text)
378
{
379
  int tmp = -1;
380
  if (argi < argc) tmp = get_pint(argv[argi++]);
381
  if (tmp < min || tmp > max) {
382
    fprintf(stderr, "tst_fx2loop-F: %s\n", text);
383
    exit(EXIT_FAILURE);
384
  }
385
  return tmp;
386
}
387
 
388
/*--------------------------------------------------------------------------*/
389
 
390
void do_write(uint16_t* buf, int nw)
391
{
392
  int rc;
393
  int i;
394
  int ntrans;
395
  int tout = 1000;
396
  int ep = 4;
397
 
398
  usb_claim();
399
  rc = libusb_bulk_transfer(pUsbDevHdl, ep,
400
                            (unsigned char *)buf, nw*2, &ntrans, tout);
401
  if (rc!=0 || ntrans != nw*2) {
402
    fprintf(stderr, "tst_fx2loop-E: bulk write failed ntrans=%d rc=%d: %s \n",
403
            ntrans, rc, usb_strerror(rc));
404
  } else {
405
    prt_time();
406
    printf("write %4d word:", nw);
407
    for (i = 0; i < nw; i++) printf(" %4.4x", buf[i]);
408
    printf("\n");
409
  }
410
  usb_release();
411
 
412
  return;
413
}
414
 
415
/*--------------------------------------------------------------------------*/
416
 
417
void do_read(int ep)
418
{
419
  int rc;
420
  int i;
421
  int ntrans;
422
  uint16_t buf[4096];
423
  int tout = 1000;
424
  int nloop;
425
 
426
  usb_claim();
427
  for (nloop=0;;nloop++) {
428
    rc = libusb_bulk_transfer(pUsbDevHdl, ep|0x80,
429
                              (unsigned char *)buf, 2*4096, &ntrans, tout);
430
 
431
    if (ntrans==0 && rc) {
432
      if (rc==LIBUSB_ERROR_TIMEOUT && ntrans==0 && nloop>0) break;
433
      fprintf(stderr, "tst_fx2loop-E: bulk read failed ntrans=%d rc=%d: %s \n",
434
              ntrans, rc, usb_strerror(rc));
435
      break;
436
    }
437
    prt_time();
438
    printf("read  %4d word:", ntrans/2);
439
    int nprt = ntrans/2;
440 22 wfjm
    if (nprt > 9) nprt = 9;
441 17 wfjm
    for (i = 0; i < nprt; i++)  printf(" %4.4x", (uint16_t)buf[i]);
442
    printf("\n");
443
    if (nsigint>0) break;
444
  }
445
  usb_release();
446
  return;
447
}
448
 
449
/*----------------------------------------------------------*/
450
void pollfd_add(int fd, short events, void *user_data)
451
{
452
  if (pollfd_nfds >= 16) {
453
    fprintf(stderr, "tst_fx2loop-F: pollfd list overflow\n");
454
    exit(EXIT_FAILURE);
455
  }
456
  if (par_trace) {
457
    prt_time();
458
    printf("pollfd_add: fd=%3d evt=%4.4x\n", fd, events);
459
  }
460
  pollfd_fds[pollfd_nfds].fd      = fd;
461
  pollfd_fds[pollfd_nfds].events  = events;
462
  pollfd_fds[pollfd_nfds].revents = 0;
463
  pollfd_nfds += 1;
464
  return;
465
}
466
 
467
/*----------------------------------------------------------*/
468
void pollfd_remove(int fd, void *user_data)
469
{
470
  int iw = 0;
471
  int ir = 0;
472
  if (par_trace) {
473
    prt_time();
474
    printf("pollfd_remove: fd=%3d\n", fd);
475
  }
476
  for (ir = 0; ir < pollfd_nfds; ir++) {
477
    if (pollfd_fds[ir].fd     != fd) {
478
      pollfd_fds[iw].fd      = pollfd_fds[ir].fd;
479
      pollfd_fds[iw].events  = pollfd_fds[ir].events;
480
      pollfd_fds[iw].revents = pollfd_fds[ir].revents;
481
      iw += 1;
482
    }
483
  }
484
  pollfd_nfds = iw;
485
  return;
486
}
487
 
488
/*----------------------------------------------------------*/
489
void pollfd_init()
490
{
491
  const struct libusb_pollfd** plist = libusb_get_pollfds(pUsbContext);
492
  const struct libusb_pollfd** p;
493
 
494
  for (p = plist; *p !=0; p++) {
495
    pollfd_add((*p)->fd, (*p)->events, NULL);
496
  }
497
 
498
  free(plist);
499
 
500
  libusb_set_pollfd_notifiers(pUsbContext, pollfd_add, pollfd_remove,NULL);
501
 
502
  return;
503
}
504
 
505
/*----------------------------------------------------------*/
506
int keep_running()
507
{
508
  if (nsigint > 0) return 0;
509
  if (par_nsec > 0 && (get_time()-t_start) > par_nsec) return 0;
510
  return 1;
511
 
512
}
513
 
514
/* forward declaration needed... */
515
void cb_rxblast(struct libusb_transfer *t);
516
 
517
/*----------------------------------------------------------*/
518
void que_write()
519
{
520
  int rc;
521
  int i;
522
  int nw = 512*dsc_rx.par_nfrm/2;
523
  int length = 2*nw;
524
  uint16_t* pdat;
525
 
526
  struct libusb_transfer* t = libusb_alloc_transfer(0);
527
 
528
  t->dev_handle = pUsbDevHdl;
529
  t->flags      = LIBUSB_TRANSFER_FREE_TRANSFER | LIBUSB_TRANSFER_FREE_BUFFER;
530
  t->endpoint   = 4;
531
  t->type       = LIBUSB_TRANSFER_TYPE_BULK;
532
  t->timeout    = 1000;
533
  t->status     = 0;
534
  t->buffer     = malloc(length);
535
  t->length     = length;
536
  t->actual_length = 0;
537
  t->callback   = cb_rxblast;
538
  t->user_data  = 0;
539
 
540
  pdat = (uint16_t*)(t->buffer);
541
  for (i = 0; i < nw; i++) *pdat++ = dsc_rx.cval++;
542
 
543
  rc = libusb_submit_transfer(t);
544
  if (rc) bad_usbcall_exit("libusb_submit_transfer()", rc);
545
 
546
  nreq += 1;
547
 
548
  if (par_trace) {
549
    prt_time();
550
    printf("que_write: ep=%1d l=%5d\n", t->endpoint&(~0x80), t->length);
551
  }
552
 
553
  return;
554
}
555
 
556
/*----------------------------------------------------------*/
557
void que_read(int ep, int nb, libusb_transfer_cb_fn cb)
558
{
559
  int rc;
560
  int length = 512*nb;
561
 
562
  struct libusb_transfer* t = libusb_alloc_transfer(0);
563
 
564
  t->dev_handle = pUsbDevHdl;
565
  t->flags      = LIBUSB_TRANSFER_FREE_TRANSFER | LIBUSB_TRANSFER_FREE_BUFFER;
566
  t->endpoint   = (unsigned char) (ep|0x80);
567
  t->type       = LIBUSB_TRANSFER_TYPE_BULK;
568
  t->timeout    = 1000;
569
  t->status     = 0;
570
  t->buffer     = malloc(length);
571
  t->length     = length;
572
  t->actual_length = 0;
573
  t->callback   = cb;
574
  t->user_data  = 0;
575
 
576
  rc = libusb_submit_transfer(t);
577
  if (rc) bad_usbcall_exit("libusb_submit_transfer()", rc);
578
 
579
  nreq += 1;
580
 
581
  if (par_trace) {
582
    prt_time();
583
    printf("que_read: ep=%1d l=%5d\n", t->endpoint&(~0x80), t->length);
584
  }
585
 
586
  return;
587
}
588
 
589
/*----------------------------------------------------------*/
590
void send_msg()
591
{
592
  int rc;
593
  int i;
594
  int nw = par_nwmsg;
595
  int length;
596
  uint16_t* pdat;
597
 
598
  if (par_nwrndm) nw = 1 + (random() % par_nwmsg);
599
  length = 2 * nw;
600
  cur_nwmsg = nw;
601
 
602
  struct libusb_transfer* t = libusb_alloc_transfer(0);
603
 
604
  t->dev_handle = pUsbDevHdl;
605
  t->flags      = LIBUSB_TRANSFER_FREE_TRANSFER | LIBUSB_TRANSFER_FREE_BUFFER;
606
  t->endpoint   = 4;
607
  t->type       = LIBUSB_TRANSFER_TYPE_BULK;
608
  t->timeout    = 1000;
609
  t->status     = 0;
610
  t->buffer     = malloc(length);
611
  t->length     = length;
612
  t->actual_length = 0;
613
  t->callback   = cb_rxblast;
614
  t->user_data  = 0;
615
 
616
  pdat = (uint16_t*)(t->buffer);
617
  for (i = 0; i < nw-1; i++) *pdat++ = dsc_rx.cval++;
618
  *pdat++ = 0xdead;
619
 
620
  rc = libusb_submit_transfer(t);
621
  if (rc) bad_usbcall_exit("libusb_submit_transfer()", rc);
622
 
623
  nreq += 1;
624
 
625
  if (par_trace) {
626
    prt_time();
627
    printf("send_msg: ep=%1d l=%5d", t->endpoint&(~0x80), t->length);
628
    printf(" buf=%4.4x,..", ((uint16_t*)(t->buffer))[0]);
629
    for (i = nw-2; i < nw; i++) {
630
      printf(",%4.4x", ((uint16_t*)(t->buffer))[i]);
631
    }
632
    printf("\n");
633
  }
634
 
635
  return;
636
}
637
 
638
/*----------------------------------------------------------*/
639
void cb_rxblast(struct libusb_transfer *t)
640
{
641
  nreq -= 1;
642
 
643
  if (par_trace) {
644
    prt_time();
645
    printf("cb_rx : ep=%d l=%5d al=%5d\n",
646
           t->endpoint&(~0x80), t->length, t->actual_length);
647
  }
648
 
649
  bad_transfer_exit(t, "cb_rxblast");
650
  dsc_rx.stat_nbuf += 1;
651
  dsc_rx.stat_nbyt += t->actual_length;
652
 
653
  if (par_nwmsg==0 && keep_running()) que_write();
654
 
655
  return;
656
}
657
 
658
/*----------------------------------------------------------*/
659
void cb_txblast(struct libusb_transfer *t, int ep, libusb_transfer_cb_fn cb,
660
                struct dsc_queue* pdsc)
661
{
662
  nreq -= 1;
663
 
664
  if (par_trace) {
665
    prt_time();
666
    printf("cb_txx: ep=%d l=%5d al=%5d\n",
667
           t->endpoint&(~0x80), t->length, t->actual_length);
668
  }
669
 
670
  bad_transfer_exit(t, "cb_txblast");
671
  if (t->actual_length > 0) {
672
    uint16_t* pdat = (uint16_t*)(t->buffer);
673
    int nw = t->actual_length/2;
674
    int i;
675
    if (pdsc->stat_nbuf == 0) pdsc->cval = pdat[0];
676
    for (i = 0; i < nw; i++) {
677
      uint16_t dat = *pdat++;
678
      if (pdsc->cval != dat) {
679
        prt_time();
680
        printf("FAIL: on ep=%d seen %4.4x expect %4.4x after %10.0f char\n",
681
               ep&(~0x80), dat, pdsc->cval, pdsc->stat_nbyt+2*i);
682
        pdsc->cval = dat;
683
      }
684
      pdsc->cval += 1;
685
    }
686
  }
687
 
688
  pdsc->stat_nbuf += 1;
689
  pdsc->stat_nbyt += t->actual_length;
690
  if (t->actual_length < t->length) pdsc->stat_npt += 1;
691
 
692
  if (keep_running()) que_read(ep, pdsc->par_nfrm, cb);
693
}
694
 
695
/*----------------------------------------------------------*/
696
void cb_tx1blast(struct libusb_transfer *t)
697
{
698
  cb_txblast(t, 6, cb_tx1blast, &dsc_tx1);
699
  return;
700
}
701
 
702
/*----------------------------------------------------------*/
703
void cb_tx2blast(struct libusb_transfer *t)
704
{
705
  cb_txblast(t, 8, cb_tx2blast, &dsc_tx2);
706
  return;
707
}
708
 
709
/*----------------------------------------------------------*/
710
void cb_txloop(struct libusb_transfer *t)
711
{
712
  nreq -= 1;
713
 
714
  if (par_trace) {
715
    prt_time();
716
    printf("cb_txl: ep=%d l=%5d al=%5d\n",
717
           t->endpoint&(~0x80), t->length, t->actual_length);
718
  }
719
 
720
  bad_transfer_exit(t, "cb_txloop");
721
  if (t->actual_length > 0) {
722
    uint16_t* pdat = (uint16_t*)(t->buffer);
723
    int nw = t->actual_length/2;
724
    int i;
725
 
726
    for (i = 0; i < nw; i++) {
727
      uint16_t dat = *pdat++;
728
 
729
      if (cur_nwmsg > 0) {
730
        uint16_t dat_exp = (cur_nwmsg>1) ? dsc_tx1.cval++ : 0xdead;
731
        if (dat_exp != dat) {
732
          prt_time();
733
          printf("FAIL: on ep=6 seen %4.4x expect %4.4x after %10.0f char\n",
734
                 dat, dat_exp, dsc_tx1.stat_nbyt+2*i);
735
          if (cur_nwmsg>1) dsc_tx1.cval = dat + 1;
736
        }
737
        cur_nwmsg -= 1;
738
        if (cur_nwmsg==0 && dat==0xdead) stat_nmsg += 1;
739
      } else {
740
        prt_time();
741
        printf("FAIL: on ep=6 seen %4.4x unexpected after %10.0f char\n",
742
               dat, dsc_tx1.stat_nbyt+2*i);
743
      }
744
    }
745
  }
746
 
747
  dsc_tx1.stat_nbuf += 1;
748
  dsc_tx1.stat_nbyt += t->actual_length;
749
  if (t->actual_length < t->length) dsc_tx1.stat_npt += 1;
750
 
751
  if (cur_nwmsg==0) {                       /* end of message seen */
752
    if (keep_running()) {
753
      send_msg();
754
    } else {
755
      if (par_trace) { prt_time(); printf("set endpoll = 1\n"); }
756
      endpoll = 1;
757
    }
758
  }
759
 
760
  que_read(6, dsc_tx1.par_nfrm, cb_txloop);
761
 
762
  return;
763
}
764
 
765
/*----------------------------------------------------------*/
766
void tx_pipe_drain(int ep)
767
{
768
  unsigned char buf[16384];
769
  int ntrans;
770
  int rc = libusb_bulk_transfer(pUsbDevHdl, ep|0x80,
771
                                buf, sizeof(buf), &ntrans, 10);
772
  if (rc == LIBUSB_ERROR_TIMEOUT) return;
773
  if (rc) bad_usbcall_exit("pipe drain: libusb_bulk_transfer()", rc);
774
 
775
  fprintf(stderr, "tst_fx2loop-I: pipe drain for ep=%d: ntrans=%d\n",
776
          ep&(~0x80), ntrans);
777
 
778
  return;
779
}
780
 
781
/*--------------------------------------------------------------------------*/
782
void do_run()
783
{
784
  int rc;
785
  int fd_timer = -1;
786
  int i;
787
 
788
  struct itimerspec tspec;
789
  struct dsc_queue dsc_rx_last  = dsc_rx;
790
  struct dsc_queue dsc_tx1_last = dsc_tx1;
791
  struct dsc_queue dsc_tx2_last = dsc_tx2;
792
 
793
  if (par_trace) {
794
    prt_time();
795
    printf("rx:nf=%d,nq=%d; tx1:nf=%d,nq=%d; tx2:nf=%d,nq=%d\n",
796
           dsc_rx.par_nfrm, dsc_rx.par_nque,
797
           dsc_tx1.par_nfrm, dsc_tx2.par_nque,
798
           dsc_tx2.par_nfrm, dsc_tx2.par_nque);
799
  }
800
 
801
  /* setup pollfd list */
802
  fd_timer = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
803
  if (fd_timer < 0) bad_syscall_exit("timerfd_create() failed", fd_timer);
804
  tspec.it_interval.tv_sec  = 1;
805
  tspec.it_interval.tv_nsec = 0;
806
  tspec.it_value.tv_sec  = 1;
807
  tspec.it_value.tv_nsec = 0;
808
  rc = timerfd_settime(fd_timer, 0, &tspec, NULL);
809
  if (rc<0) bad_syscall_exit("timerfd_settime() failed", rc);
810
  pollfd_fds[0].fd      = fd_timer;
811
  pollfd_fds[0].events  = POLLIN;
812
  pollfd_fds[0].revents = 0;
813
  pollfd_nfds = 1;
814
 
815
  pollfd_init();
816
 
817
  /* setup loop */
818
  if (par_nwmsg > 0) {
819
    dsc_rx.par_nfrm = 0;
820
    dsc_rx.par_nque = 0;
821
    if (dsc_tx1.par_nfrm == 0) dsc_tx1.par_nfrm = 1;
822
    if (dsc_tx1.par_nque == 0) dsc_tx1.par_nque = 1;
823
 
824
    tx_pipe_drain(6);                       /* drain tx1 */
825
    for (i = 0; i < dsc_tx1.par_nque; i++)  /* prime tx1 */
826
      que_read(6, dsc_tx1.par_nfrm, cb_txloop);
827
    send_msg();
828
  }
829
 
830
  /* setup rxblast */
831
  if (dsc_rx.par_nfrm > 0) {
832
    int i;
833
    if (dsc_rx.par_nque == 0) dsc_rx.par_nque = 1;
834
    for (i = 0; i < dsc_rx.par_nque; i++) que_write();
835
  }
836
 
837
  /* setup txblast */
838
  if (par_nwmsg==0 && dsc_tx1.par_nfrm>0) {
839
    int i;
840
    if (dsc_tx1.par_nque == 0) dsc_tx1.par_nque = 1;
841
    for (i = 0; i < dsc_tx1.par_nque; i++)
842
      que_read(6, dsc_tx1.par_nfrm, cb_tx1blast);
843
  }
844
 
845
  /* setup tx2blast */
846
  if (dsc_tx2.par_nfrm > 0) {
847
    int i;
848
    if (dsc_tx2.par_nque == 0) dsc_tx2.par_nque = 1;
849
    for (i = 0; i < dsc_tx2.par_nque; i++)
850
      que_read(8, dsc_tx2.par_nfrm, cb_tx2blast);
851
  }
852
 
853
  t_start = get_time();
854
 
855
  while(nreq>0 && endpoll==0) {
856
    uint64_t tbuf;
857
    rc = poll(pollfd_fds, pollfd_nfds, 2000);
858
    if (rc==-1 && errno==EINTR) continue;
859
    if (rc < 0) bad_syscall_exit("poll() failed", rc);
860
    if (rc == 0) fprintf(stderr, "tst_fx2loop-I: poll() timeout\n");
861
 
862
    if (par_trace) {
863
      int i;
864
      prt_time();
865
      printf("poll: rc=%d:", rc);
866
      for (i = 0; i < pollfd_nfds; i++) {
867
        printf(" %d,%2.2x", pollfd_fds[i].fd, pollfd_fds[i].revents);
868
      }
869
      printf("\n");
870
    }
871
 
872
    if (pollfd_fds[0].revents == POLLIN) {
873
      errno = EBADMSG;                      /* to be reported on short read */
874
      rc = read(fd_timer, &tbuf, sizeof(tbuf));
875
      if (rc != sizeof(tbuf)) bad_syscall_exit("read(fd_timer,...) failed", rc);
876
      if (par_stat) {
877
        prt_time();
878
        if (par_nwmsg>0 || dsc_rx.par_nque>0) {
879
          double nbuf = dsc_rx.stat_nbuf - dsc_rx_last.stat_nbuf;
880
          double nbyt = dsc_rx.stat_nbyt - dsc_rx_last.stat_nbyt;
881
          printf("rx: %5.0f,%7.1f  ", nbuf, nbyt/1000.);
882
        }
883
        if (dsc_tx1.par_nque > 0 ) {
884
          double nbuf = dsc_tx1.stat_nbuf - dsc_tx1_last.stat_nbuf;
885
          double nbyt = dsc_tx1.stat_nbyt - dsc_tx1_last.stat_nbyt;
886
          printf("tx1: %5.0f,%7.1f  ", nbuf, nbyt/1000.);
887
        }
888
        if (dsc_tx2.par_nque > 0 ) {
889
          double nbuf = dsc_tx2.stat_nbuf - dsc_tx2_last.stat_nbuf;
890
          double nbyt = dsc_tx2.stat_nbyt - dsc_tx2_last.stat_nbyt;
891
          printf("tx2: %5.0f,%7.1f  ", nbuf, nbyt/1000.);
892
        }
893
        printf("\n");
894
        dsc_rx_last  = dsc_rx;
895
        dsc_tx1_last = dsc_tx1;
896
        dsc_tx2_last = dsc_tx2;
897
      }
898
    } else {
899
      struct timeval tv;
900
      tv.tv_sec  = 0;
901
      tv.tv_usec = 0;
902
      rc = libusb_handle_events_timeout(pUsbContext, &tv);
903
      //setting the timeval pointer to NULL should work, but doesn't (in 1.0.6)
904
      //rc = libusb_handle_events_timeout(pUsbContext, 0);
905
      if (rc) bad_usbcall_exit("libusb_handle_events_timeout()", rc);
906
    }
907
  }
908
 
909
  return;
910
}
911
 
912
/*--------------------------------------------------------------------------*/
913
 
914
void do_stat()
915
{
916
  printf("run statistics:\n");
917
  printf("runtime  : %13.3f\n", get_time()-t_start);
918
  printf("nbuf_rx  : %13.0f\n", dsc_rx.stat_nbuf);
919
  printf("nbyt_rx  : %13.0f\n", dsc_rx.stat_nbyt);
920
  printf("nbuf_tx1 : %13.0f\n", dsc_tx1.stat_nbuf);
921
  printf("nbyt_tx1 : %13.0f\n", dsc_tx1.stat_nbyt);
922
  printf("npt_tx1  : %13.0f\n", dsc_tx1.stat_npt);
923
  printf("nbuf_tx2 : %13.0f\n", dsc_tx2.stat_nbuf);
924
  printf("nbyt_tx2 : %13.0f\n", dsc_tx2.stat_nbyt);
925
  printf("npt_tx2  : %13.0f\n", dsc_tx2.stat_npt);
926
  printf("nmsg     : %13.0f\n", stat_nmsg);
927
  return;
928
}
929
 
930
/*--------------------------------------------------------------------------*/
931
 
932
void usb_claim()
933
{
934
  int rc = libusb_claim_interface(pUsbDevHdl, 0);
935
  if (rc) bad_usbcall_exit("libusb_claim_interface()", rc);
936
  return;
937
}
938
 
939
/*--------------------------------------------------------------------------*/
940
 
941
void usb_release()
942
{
943
  int rc = libusb_release_interface(pUsbDevHdl, 0);
944
  if (rc) bad_usbcall_exit("libusb_release_interface()", rc);
945
  return;
946
}
947
 
948
/*--------------------------------------------------------------------------*/
949
 
950
char* usb_strerror(int rc)
951
{
952
  switch(rc) {
953
    case LIBUSB_SUCCESS:
954
      return "";
955
    case LIBUSB_ERROR_IO:
956
      return "Input/output error";
957
    case LIBUSB_ERROR_INVALID_PARAM:
958
      return "Invalid parameter";
959
    case LIBUSB_ERROR_ACCESS:
960
      return "Access denied";
961
    case LIBUSB_ERROR_NO_DEVICE:
962
      return "No such device";
963
    case LIBUSB_ERROR_NOT_FOUND:
964
      return "Entity not found";
965
    case LIBUSB_ERROR_BUSY:
966
      return "Resource busy";
967
    case LIBUSB_ERROR_TIMEOUT:
968
      return "Operation timed out";
969
    case LIBUSB_ERROR_OVERFLOW:
970
      return "Overflow";
971
    case LIBUSB_ERROR_PIPE:
972
      return "Pipe error";
973
    case LIBUSB_ERROR_INTERRUPTED:
974
      return "System call interrupted";
975
    case LIBUSB_ERROR_NO_MEM:
976
      return "Insufficient memory";
977
    case LIBUSB_ERROR_NOT_SUPPORTED:
978
      return "Operation not supported";
979
    case LIBUSB_ERROR_OTHER:
980
      return "Other error";
981
    default:
982
      return "Unknown libusb error code";
983
  }
984
}
985
 
986
/*--------------------------------------------------------------------------*/
987
 
988
void prt_time(void)
989
{
990
  struct timeval tv;
991
  struct timezone tz;
992
  struct tm tmval;
993
 
994
  gettimeofday(&tv, &tz);
995
  localtime_r(&tv.tv_sec, &tmval);
996
  printf("%02d:%02d:%02d.%06d: ", tmval.tm_hour, tmval.tm_min, tmval.tm_sec,
997
         (int) tv.tv_usec);
998
}
999
 
1000
/*--------------------------------------------------------------------------*/
1001
 
1002
double get_time(void)
1003
{
1004
  struct timeval tv;
1005
  struct timezone tz;
1006
  gettimeofday(&tv, &tz);
1007
  return (double)tv.tv_sec + 1.e-6 * (double)tv.tv_usec;
1008
}
1009
 
1010
/*--------------------------------------------------------------------------*/
1011
 
1012
void bad_syscall_exit(const char* text, int rc)
1013
{
1014
  fprintf(stderr, "tst_fx2loop-F: %s failed with rc=%d errno=%d : %s\n",
1015
          text, rc, errno, strerror(errno));
1016
  exit(EXIT_FAILURE);
1017
}
1018
 
1019
/*--------------------------------------------------------------------------*/
1020
 
1021
void bad_usbcall_exit(const char* text, int rc)
1022
{
1023
  fprintf(stderr, "tst_fx2loop-F: %s failed with rc=%d: %s\n",
1024
          text, rc, usb_strerror(rc));
1025
  exit(EXIT_FAILURE);
1026
}
1027
 
1028
/*--------------------------------------------------------------------------*/
1029
 
1030
void bad_transfer_exit(struct libusb_transfer *t, const char* text)
1031
{
1032
  const char* etext = 0;
1033
 
1034
  if (t->status == LIBUSB_TRANSFER_ERROR)     etext = "ERROR";
1035
  if (t->status == LIBUSB_TRANSFER_STALL)     etext = "STALL";
1036
  if (t->status == LIBUSB_TRANSFER_NO_DEVICE) etext = "NO_DEVICE";
1037
  if (t->status == LIBUSB_TRANSFER_OVERFLOW)  etext = "OVERFLOW";
1038
 
1039
  if (etext == 0) return;
1040
 
1041
  fprintf(stderr, "tst_fx2loop-F: transfer failure in %s on ep=%d: %s\n",
1042
          text, (int)(t->endpoint&(~0x80)), etext);
1043
  exit(EXIT_FAILURE);
1044
}
1045
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.