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

Subversion Repositories w11

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

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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