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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [io/] [usb/] [slave/] [current/] [tests/] [common.c] - Blame information for rev 825

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

Line No. Rev Author Line
1 786 skrzyp
/*{{{  Banner                                                   */
2
 
3
/*=================================================================
4
//
5
//        common.c
6
//
7
//        USB testing - code common to host and target
8
//
9
//==========================================================================
10
// ####ECOSGPLCOPYRIGHTBEGIN####
11
// -------------------------------------------
12
// This file is part of eCos, the Embedded Configurable Operating System.
13
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
14
//
15
// eCos is free software; you can redistribute it and/or modify it under
16
// the terms of the GNU General Public License as published by the Free
17
// Software Foundation; either version 2 or (at your option) any later
18
// version.
19
//
20
// eCos is distributed in the hope that it will be useful, but WITHOUT
21
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23
// for more details.
24
//
25
// You should have received a copy of the GNU General Public License
26
// along with eCos; if not, write to the Free Software Foundation, Inc.,
27
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
28
//
29
// As a special exception, if other files instantiate templates or use
30
// macros or inline functions from this file, or you compile this file
31
// and link it with other works to produce a work based on this file,
32
// this file does not by itself cause the resulting work to be covered by
33
// the GNU General Public License. However the source code for this file
34
// must still be made available in accordance with section (3) of the GNU
35
// General Public License v2.
36
//
37
// This exception does not invalidate any other reasons why a work based
38
// on this file might be covered by the GNU General Public License.
39
// -------------------------------------------
40
// ####ECOSGPLCOPYRIGHTEND####
41
//==========================================================================
42
//#####DESCRIPTIONBEGIN####
43
//
44
// This module contains some definitions and functions that are common to
45
// both the host and target side of USB testing, for example filling in
46
// a buffer with well-known data and validating the contents at the other end.
47
// The module is #include'd by other code rather than compiled separately,
48
// which simplifies the build process.
49
//
50
// Author(s):     bartv
51
// Date:          2001-08-14
52
//####DESCRIPTIONEND####
53
//==========================================================================
54
*/
55
 
56
/*}}}*/
57
 
58
/*{{{  Simple data pack and unpack operations                   */
59
 
60
// ----------------------------------------------------------------------------
61
// Utilities to pack and unpack data into buffers. 
62
//
63
// Integers are transferred with 32 bits of precision, irrespective
64
// of the capabilities of either target and host.
65
 
66
static inline void
67
pack_int(int datum, unsigned char* buffer, int* index_ptr)
68
{
69
    int index = *index_ptr;
70
    buffer[index++] = (datum >>  0) & 0x0FF;
71
    buffer[index++] = (datum >>  8) & 0x0FF;
72
    buffer[index++] = (datum >> 16) & 0x0FF;
73
    buffer[index++] = (datum >> 24) & 0x0FF;
74
    *index_ptr = index;
75
}
76
 
77
static inline int
78
unpack_int(unsigned char* buffer, int* index_ptr)
79
{
80
    int index   = *index_ptr;
81
    int result;
82
 
83
    result  = (buffer[index++] <<  0);
84
    result |= (buffer[index++] <<  8);
85
    result |= (buffer[index++] << 16);
86
    result |= (buffer[index++] << 24);
87
    *index_ptr = index;
88
    return result;
89
}
90
 
91
/*}}}*/
92
/*{{{  Buffer data and validation                               */
93
 
94
// ----------------------------------------------------------------------------
95
// The data required for a given test. For some test cases, for
96
// example when trying to achieve maximum throughput, it does not
97
// matter what data is transferred. For other tests it is important to
98
// validate that the data sent and received match up, and there should
99
// be some control over the actual data: some tests might want to send
100
// a long sequence of byte 0, while others want to send more random data
101
// for which a simple random number generator is useful.
102
//
103
// Exactly the same routines are used on both host and target to fill in
104
// and check buffers, and they are sufficiently simple that the routines
105
// should get compiled in compatible ways.
106
//
107
// There is no support at present for sending specific data, e.g. a
108
// specific ethernet packet that appears to be causing problems. Knowledge
109
// of specific data cannot be compiled into the test code, so the only
110
// way to implement something like this would be to transfer the
111
// problematical data over the USB bus in order to determine whether or
112
// not the bus is capable of reliably transferring this data. That is
113
// not entirely impossible (checksums, use of alternative endpoints),
114
// but it is not implemented.
115
//
116
// An alternative approach would be to support a bounce operation
117
// involving both an IN and an OUT endpoint, doing validation only on
118
// the host. Again that is not yet implemented.
119
//
120
// The byte_fill and int_fill options are actually redundant because the
121
// same effect can be achieved using a multiplier of 1 and an increment
122
// of 0, but they can be implemented much more efficiently so may be
123
// useful for benchmarks.
124
 
125
typedef enum usbtestdata {
126
    usbtestdata_none        = 0,       // There is nothing useful in the data
127
    usbtestdata_bytefill    = 1,       // The data consists of a single byte, repeated
128
    usbtestdata_wordfill    = 2,       // Or a single integer
129
    usbtestdata_byteseq     = 3,       // Or a pseudo-random sequence (a * seed) + b
130
    usbtestdata_wordseq     = 4        // as either bytes or integers
131
} usbtestdata;
132
 
133
typedef struct UsbTestData {
134
    usbtestdata     format;
135
    int             seed;
136
    int             multiplier; // 1103515245
137
    int             increment;  // 12345
138
    int             transfer_seed_multiplier;
139
    int             transfer_seed_increment;
140
    int             transfer_multiplier_multiplier;
141
    int             transfer_multiplier_increment;
142
    int             transfer_increment_multiplier;
143
    int             transfer_increment_increment;
144
} UsbTestData;
145
 
146
static void
147
usbtest_fill_buffer(UsbTestData* how, unsigned char* buffer, int length)
148
{
149
    switch(how->format)
150
    {
151
      case usbtestdata_none:
152
        return;
153
 
154
      case usbtestdata_bytefill:
155
        // Leave it to the system to optimise memset().
156
        memset(buffer, (how->seed & 0x0FF), length);
157
        break;
158
 
159
      case usbtestdata_wordfill:
160
      {
161
          // The buffer may not be a multiple of four bytes, so the last entry is always
162
          // zero'd.
163
          int i;
164
          int index = 0;
165
          for (i = 0; i < (length / 4); i++) {
166
              pack_int(how->seed, buffer, &index);
167
          }
168
          pack_int(0, buffer, &index);
169
          break;
170
      }
171
 
172
      case usbtestdata_byteseq:
173
      {
174
          int i;
175
          for (i = 0; i < length; i++) {
176
              buffer[i] = (how->seed & 0x00FF);
177
              how->seed *= how->multiplier;
178
              how->seed += how->increment;
179
          }
180
          break;
181
      }
182
 
183
      case usbtestdata_wordseq:
184
      {
185
          int i;
186
          int index = 0;
187
          for (i = 0; i < (length / 4); i++) {
188
              pack_int(how->seed, buffer, &index);
189
              how->seed *= how->multiplier;
190
              how->seed += how->increment;
191
          }
192
          pack_int(0, buffer, &index);
193
          break;
194
      }
195
    }
196
 
197
    // After each transfer update the seed, multiplier and increment
198
    // ready for the next one.
199
    how->seed       *= how->transfer_seed_multiplier;
200
    how->seed       += how->transfer_seed_increment;
201
    how->multiplier *= how->transfer_multiplier_multiplier;
202
    how->multiplier += how->transfer_multiplier_increment;
203
    how->increment  *= how->transfer_increment_multiplier;
204
    how->increment  += how->transfer_increment_increment;
205
}
206
 
207
static int
208
usbtest_check_buffer(UsbTestData* how, unsigned char* buffer, int length)
209
{
210
    int result  = 1;
211
 
212
    switch(how->format) {
213
      case usbtestdata_none:
214
        break;
215
 
216
      case usbtestdata_bytefill:
217
      {
218
          int i;
219
          result = 1;
220
          for (i = 0; i < length; i++) {
221
              if (buffer[i] != (how->seed & 0x00FF)) {
222
                  result = 0;
223
                  break;
224
              }
225
          }
226
          break;
227
      }
228
 
229
      case usbtestdata_wordfill:
230
      {
231
          int i;
232
          int index = 0;
233
          for (i = 0; i < (length / 4); i++) {
234
              int datum = unpack_int(buffer, &index);
235
              if (datum != (how->seed & 0x0FFFFFFFF)) {
236
                  result = 0;
237
                  break;
238
              }
239
          }
240
          for (i = 4 * i; result && (i < length); i++) {
241
              if (0 != buffer[i]) {
242
                  result = 0;
243
                  break;
244
              }
245
          }
246
          break;
247
      }
248
 
249
      case usbtestdata_byteseq:
250
      {
251
          int i;
252
          for (i = 0; i < length; i++) {
253
              if (buffer[i] != (how->seed & 0x00FF)) {
254
                  result = 0;
255
                  break;
256
              }
257
              how->seed *= how->multiplier;
258
              how->seed += how->increment;
259
          }
260
          break;
261
      }
262
 
263
      case usbtestdata_wordseq:
264
      {
265
          int   i;
266
          int   index = 0;
267
 
268
          for (i = 0; i < (length / 4); i++) {
269
              int datum = unpack_int(buffer, &index);
270
              if (datum != (how->seed & 0x0FFFFFFFF)) {
271
                  result = 0;
272
                  break;
273
              }
274
              how->seed *= how->multiplier;
275
              how->seed += how->increment;
276
          }
277
          for (i = 4 * i; result && (i < length); i++) {
278
              if (0 != buffer[i]) {
279
                  result = 0;
280
                  break;
281
              }
282
          }
283
          break;
284
      }
285
    }
286
 
287
    // After each transfer update the seed, multiplier and increment
288
    // ready for the next transfer.
289
    how->seed       *= how->transfer_seed_multiplier;
290
    how->seed       += how->transfer_seed_increment;
291
    how->multiplier *= how->transfer_multiplier_multiplier;
292
    how->multiplier += how->transfer_multiplier_increment;
293
    how->increment  *= how->transfer_increment_multiplier;
294
    how->increment  += how->transfer_increment_increment;
295
 
296
    return result;
297
}
298
 
299
#ifdef HOST
300
static void
301
pack_usbtestdata(UsbTestData* data, unsigned char* buf, int* index)
302
{
303
    pack_int((int)data->format,                         buf, index);
304
    pack_int((int)data->seed,                           buf, index);
305
    pack_int((int)data->multiplier,                     buf, index);
306
    pack_int((int)data->increment,                      buf, index);
307
    pack_int((int)data->transfer_seed_multiplier,       buf, index);
308
    pack_int((int)data->transfer_seed_increment,        buf, index);
309
    pack_int((int)data->transfer_multiplier_multiplier, buf, index);
310
    pack_int((int)data->transfer_multiplier_increment,  buf, index);
311
    pack_int((int)data->transfer_increment_multiplier,  buf, index);
312
    pack_int((int)data->transfer_increment_increment,   buf, index);
313
}
314
#endif
315
 
316
#ifdef TARGET
317
static void
318
unpack_usbtestdata(UsbTestData* data, unsigned char* buf, int* index)
319
{
320
    data->format                        = (usbtestdata) unpack_int(buf, index);
321
    data->seed                          = unpack_int(buf, index);
322
    data->multiplier                    = unpack_int(buf, index);
323
    data->increment                     = unpack_int(buf, index);
324
    data->transfer_seed_multiplier      = unpack_int(buf, index);
325
    data->transfer_seed_increment       = unpack_int(buf, index);
326
    data->transfer_multiplier_multiplier= unpack_int(buf, index);
327
    data->transfer_multiplier_increment = unpack_int(buf, index);
328
    data->transfer_increment_multiplier = unpack_int(buf, index);
329
    data->transfer_increment_increment  = unpack_int(buf, index);
330
}
331
#endif
332
 
333
/*}}}*/
334
/*{{{  Testcase definitions                                     */
335
 
336
// ----------------------------------------------------------------------------
337
// Definitions of the supported test cases. The actual implementations need
338
// to vary between host and target.
339
 
340
typedef enum usbtest {
341
    usbtest_invalid     = 0,
342
    usbtest_bulk_out    = 1,
343
    usbtest_bulk_in     = 2,
344
    usbtest_control_in  = 3
345
} usbtest;
346
 
347
// What I/O mechanism should be used on the target to process data?
348
typedef enum usb_io_mechanism {
349
    usb_io_mechanism_usb    = 1,        // The low-level USB-specific API
350
    usb_io_mechanism_dev    = 2         // cyg_devio_cread() et al
351
} usb_io_mechanism;
352
 
353
// Bulk transfers. The same structure can be used for IN and OUT transfers.
354
// The endpoint number will be or'd with either USB_DIR_IN or USB_DIR_OUT,
355
// or the equivalent under eCos.
356
typedef struct UsbTest_Bulk {
357
    int                 number_packets;
358
    int                 endpoint;
359
    int                 tx_size;
360
    int                 tx_size_min;
361
    int                 tx_size_max;
362
    int                 tx_size_multiplier;
363
    int                 tx_size_divisor;
364
    int                 tx_size_increment;
365
    int                 rx_size;
366
    int                 rx_size_min;
367
    int                 rx_size_max;
368
    int                 rx_size_multiplier;
369
    int                 rx_size_divisor;
370
    int                 rx_size_increment;
371
    int                 rx_padding;
372
    int                 tx_delay;
373
    int                 tx_delay_min;
374
    int                 tx_delay_max;
375
    int                 tx_delay_multiplier;
376
    int                 tx_delay_divisor;
377
    int                 tx_delay_increment;
378
    int                 rx_delay;
379
    int                 rx_delay_min;
380
    int                 rx_delay_max;
381
    int                 rx_delay_multiplier;
382
    int                 rx_delay_divisor;
383
    int                 rx_delay_increment;
384
    usb_io_mechanism    io_mechanism;
385
    UsbTestData         data;
386
} UsbTest_Bulk;
387
 
388
#ifdef HOST
389
static void
390
pack_usbtest_bulk(UsbTest_Bulk* test, unsigned char* buffer, int* index)
391
{
392
    pack_int(test->number_packets,          buffer, index);
393
    pack_int(test->endpoint,                buffer, index);
394
    pack_int(test->tx_size,                 buffer, index);
395
    pack_int(test->tx_size_min,             buffer, index);
396
    pack_int(test->tx_size_max,             buffer, index);
397
    pack_int(test->tx_size_multiplier,      buffer, index);
398
    pack_int(test->tx_size_divisor,         buffer, index);
399
    pack_int(test->tx_size_increment,       buffer, index);
400
    pack_int(test->rx_size,                 buffer, index);
401
    pack_int(test->rx_size_min,             buffer, index);
402
    pack_int(test->rx_size_max,             buffer, index);
403
    pack_int(test->rx_size_multiplier,      buffer, index);
404
    pack_int(test->rx_size_divisor,         buffer, index);
405
    pack_int(test->rx_size_increment,       buffer, index);
406
    // There is no need to transfer the padding field. It is only of
407
    // interest on the host, and this message is being packed
408
    // for the target side.
409
    pack_int(test->tx_delay,                buffer, index);
410
    pack_int(test->tx_delay_min,            buffer, index);
411
    pack_int(test->tx_delay_max,            buffer, index);
412
    pack_int(test->tx_delay_multiplier,     buffer, index);
413
    pack_int(test->tx_delay_divisor,        buffer, index);
414
    pack_int(test->tx_delay_increment,      buffer, index);
415
    pack_int(test->rx_delay,                buffer, index);
416
    pack_int(test->rx_delay_min,            buffer, index);
417
    pack_int(test->rx_delay_max,            buffer, index);
418
    pack_int(test->rx_delay_multiplier,     buffer, index);
419
    pack_int(test->rx_delay_divisor,        buffer, index);
420
    pack_int(test->rx_delay_increment,      buffer, index);
421
    pack_int((int)test->io_mechanism,       buffer, index);
422
    pack_usbtestdata(&(test->data),         buffer, index);
423
}
424
#endif
425
 
426
#ifdef TARGET
427
static void
428
unpack_usbtest_bulk(UsbTest_Bulk* test, unsigned char* buffer, int* index)
429
{
430
    test->number_packets            = unpack_int(buffer, index);
431
    test->endpoint                  = unpack_int(buffer, index);
432
    test->tx_size                   = unpack_int(buffer, index);
433
    test->tx_size_min               = unpack_int(buffer, index);
434
    test->tx_size_max               = unpack_int(buffer, index);
435
    test->tx_size_multiplier        = unpack_int(buffer, index);
436
    test->tx_size_divisor           = unpack_int(buffer, index);
437
    test->tx_size_increment         = unpack_int(buffer, index);
438
    test->rx_size                   = unpack_int(buffer, index);
439
    test->rx_size_min               = unpack_int(buffer, index);
440
    test->rx_size_max               = unpack_int(buffer, index);
441
    test->rx_size_multiplier        = unpack_int(buffer, index);
442
    test->rx_size_divisor           = unpack_int(buffer, index);
443
    test->rx_size_increment         = unpack_int(buffer, index);
444
    test->tx_delay                  = unpack_int(buffer, index);
445
    test->tx_delay_min              = unpack_int(buffer, index);
446
    test->tx_delay_max              = unpack_int(buffer, index);
447
    test->tx_delay_multiplier       = unpack_int(buffer, index);
448
    test->tx_delay_divisor          = unpack_int(buffer, index);
449
    test->tx_delay_increment        = unpack_int(buffer, index);
450
    test->rx_delay                  = unpack_int(buffer, index);
451
    test->rx_delay_min              = unpack_int(buffer, index);
452
    test->rx_delay_max              = unpack_int(buffer, index);
453
    test->rx_delay_multiplier       = unpack_int(buffer, index);
454
    test->rx_delay_divisor          = unpack_int(buffer, index);
455
    test->rx_delay_increment        = unpack_int(buffer, index);
456
    test->io_mechanism              = (usb_io_mechanism) unpack_int(buffer, index);
457
    unpack_usbtestdata(&(test->data), buffer, index);
458
}
459
#endif
460
 
461
// A macro for moving on the next packet size. This also has to be shared between host
462
// and target, if the two got out of synch then testing would go horribly wrong.
463
//
464
// The new packet size is determined using a multiplier and increment,
465
// so to e.g. increase packet sizes by 4 bytes each time the
466
// multiplier would be 1 and the increment would be 4, or to double
467
// packet sizes the multiplier would be 2 and the increment would be
468
// 0. On underflow or overflow the code tries to adjust the packet size
469
// back to within the accepted range.
470
 
471
#define USBTEST_NEXT_TX_SIZE(_x_)                               \
472
    do {                                                        \
473
        _x_.tx_size *= _x_.tx_size_multiplier;                  \
474
        _x_.tx_size /= _x_.tx_size_divisor;                     \
475
        _x_.tx_size += _x_.tx_size_increment;                   \
476
        if (_x_.tx_size < _x_.tx_size_min) {                    \
477
            if (_x_.tx_size_min == _x_.tx_size_max) {           \
478
                _x_.tx_size = _x_.tx_size_min;                  \
479
            } else {                                            \
480
                int tmp  = _x_.tx_size_min - _x_.tx_size;       \
481
                tmp     %= _x_.tx_size_max - _x_.tx_size_min;   \
482
                _x_.tx_size = tmp + _x_.tx_size_min;            \
483
            }                                                   \
484
        } else if (_x_.tx_size > _x_.tx_size_max) {             \
485
            if (_x_.tx_size_min == _x_.tx_size_max) {           \
486
                _x_.tx_size = _x_.tx_size_max;                  \
487
            } else {                                            \
488
                int tmp  = _x_.tx_size - _x_.tx_size_max;       \
489
                tmp     %= _x_.tx_size_max - _x_.tx_size_min;   \
490
                _x_.tx_size = tmp + _x_.tx_size_min;            \
491
            }                                                   \
492
        }                                                       \
493
    } while ( 0 )
494
 
495
// A similar macro for moving on to the next receive size. This is less
496
// critical since care is taken to always receive at least the current
497
// tx size plus padding.
498
// Note that padding needs to be added by the calling code, not here,
499
// since padding is only applicable on the host-side and this macro
500
// is used on both host and target.
501
#define USBTEST_NEXT_RX_SIZE(_x_)                               \
502
    do {                                                        \
503
        _x_.rx_size *= _x_.rx_size_multiplier;                  \
504
        _x_.rx_size /= _x_.rx_size_divisor;                     \
505
        _x_.rx_size += _x_.rx_size_increment;                   \
506
        if (_x_.rx_size < _x_.rx_size_min) {                    \
507
            if (_x_.rx_size_min == _x_.rx_size_max) {           \
508
                _x_.rx_size = _x_.rx_size_min;                  \
509
            } else {                                            \
510
                int tmp  = _x_.rx_size_min - _x_.rx_size;       \
511
                tmp     %= _x_.rx_size_max - _x_.rx_size_min;   \
512
                _x_.rx_size = tmp + _x_.rx_size_min;            \
513
            }                                                   \
514
        } else if (_x_.rx_size > _x_.rx_size_max) {             \
515
            if (_x_.rx_size_min == _x_.rx_size_max) {           \
516
                _x_.rx_size = _x_.rx_size_max;                  \
517
            } else {                                            \
518
                int tmp  = _x_.rx_size - _x_.rx_size_max;       \
519
                tmp     %= _x_.rx_size_max - _x_.rx_size_min;   \
520
                _x_.rx_size = tmp + _x_.rx_size_min;            \
521
            }                                                   \
522
        }                                                       \
523
    } while ( 0 )
524
 
525
// And a macro for adjusting the transmit delay.
526
#define USBTEST_NEXT_TX_DELAY(_x_)                              \
527
    do {                                                        \
528
        _x_.tx_delay *= _x_.tx_delay_multiplier;                \
529
        _x_.tx_delay /= _x_.tx_delay_divisor;                   \
530
        _x_.tx_delay += _x_.tx_delay_increment;                 \
531
        if (_x_.tx_delay < _x_.tx_delay_min) {                  \
532
            if (_x_.tx_delay_min == _x_.tx_delay_max) {         \
533
                _x_.tx_delay = _x_.tx_delay_min;                \
534
            } else {                                            \
535
                int tmp  = _x_.tx_delay_min - _x_.tx_delay;     \
536
                tmp     %= _x_.tx_delay_max - _x_.tx_delay_min; \
537
                _x_.tx_delay = tmp + _x_.tx_delay_min;          \
538
            }                                                   \
539
        } else if (_x_.tx_delay > _x_.tx_delay_max) {           \
540
            if (_x_.tx_delay_min == _x_.tx_delay_max) {         \
541
                _x_.tx_delay = _x_.tx_delay_max;                \
542
            } else {                                            \
543
                int tmp  = _x_.tx_delay - _x_.tx_delay_max;     \
544
                tmp     %= _x_.tx_delay_max - _x_.tx_delay_min; \
545
                _x_.tx_delay = tmp + _x_.tx_delay_min;          \
546
            }                                                   \
547
        }                                                       \
548
    } while ( 0 )
549
 
550
#define USBTEST_NEXT_RX_DELAY(_x_)                              \
551
    do {                                                        \
552
        _x_.rx_delay *= _x_.rx_delay_multiplier;                \
553
        _x_.rx_delay /= _x_.rx_delay_divisor;                   \
554
        _x_.rx_delay += _x_.rx_delay_increment;                 \
555
        if (_x_.rx_delay < _x_.rx_delay_min) {                  \
556
            if (_x_.rx_delay_min == _x_.rx_delay_max) {         \
557
                _x_.rx_delay = _x_.rx_delay_min;                \
558
            } else {                                            \
559
                int tmp  = _x_.rx_delay_min - _x_.rx_delay;     \
560
                tmp     %= _x_.rx_delay_max - _x_.rx_delay_min; \
561
                _x_.rx_delay = tmp + _x_.rx_delay_min;          \
562
            }                                                   \
563
        } else if (_x_.rx_delay > _x_.rx_delay_max) {           \
564
            if (_x_.rx_delay_min == _x_.rx_delay_max) {         \
565
                _x_.rx_delay = _x_.rx_delay_max;                \
566
            } else {                                            \
567
                int tmp  = _x_.rx_delay - _x_.rx_delay_max;     \
568
                tmp     %= _x_.rx_delay_max - _x_.rx_delay_min; \
569
                _x_.rx_delay = tmp + _x_.rx_delay_min;          \
570
            }                                                   \
571
        }                                                       \
572
    } while ( 0 )
573
 
574
#define USBTEST_BULK_NEXT(_bulk_)                               \
575
    USBTEST_NEXT_TX_SIZE(_bulk_);                               \
576
    USBTEST_NEXT_RX_SIZE(_bulk_);                               \
577
    USBTEST_NEXT_TX_DELAY(_bulk_);                              \
578
    USBTEST_NEXT_RX_DELAY(_bulk_);
579
 
580
// Control transfers, receives
581
typedef struct UsbTest_ControlIn {
582
    int         number_packets;
583
    int         packet_size_initial;
584
    int         packet_size_min;
585
    int         packet_size_max;
586
    int         packet_size_multiplier;
587
    int         packet_size_increment;
588
    UsbTestData data;
589
} UsbTest_ControlIn;
590
 
591
#ifdef HOST
592
static void
593
pack_usbtest_control_in(UsbTest_ControlIn* test, unsigned char* buffer, int* index)
594
{
595
    pack_int(test->number_packets,          buffer, index);
596
    pack_int(test->packet_size_initial,     buffer, index);
597
    pack_int(test->packet_size_min,         buffer, index);
598
    pack_int(test->packet_size_max,         buffer, index);
599
    pack_int(test->packet_size_multiplier,  buffer, index);
600
    pack_int(test->packet_size_increment,   buffer, index);
601
    pack_usbtestdata(&(test->data),         buffer, index);
602
}
603
#endif
604
 
605
#ifdef TARGET
606
static void
607
unpack_usbtest_control_in(UsbTest_ControlIn* test, unsigned char* buffer, int* index)
608
{
609
    test->number_packets            = unpack_int(buffer, index);
610
    test->packet_size_initial       = unpack_int(buffer, index);
611
    test->packet_size_min           = unpack_int(buffer, index);
612
    test->packet_size_max           = unpack_int(buffer, index);
613
    test->packet_size_multiplier    = unpack_int(buffer, index);
614
    test->packet_size_increment     = unpack_int(buffer, index);
615
    unpack_usbtestdata(&(test->data), buffer, index);
616
}
617
#endif
618
 
619
// For now control packet sizes are adjusted in exactly the same way as bulk transfers.
620
#define USBTEST_CONTROL_NEXT_PACKET_SIZE(_packet_size_, _control_)                                          \
621
    _packet_size_ = (_packet_size_ * _control_.packet_size_multiplier) + _control_.packet_size_increment;   \
622
    if (_packet_size_ < _control_.packet_size_min) {                                                        \
623
        _packet_size_ += _control_.packet_size_max - _control_.packet_size_min;                             \
624
        if (_packet_size_ < _control_.packet_size_min) {                                                    \
625
            _packet_size_ = _control_.packet_size_initial;                                                  \
626
        }                                                                                                   \
627
    } else if (_packet_size_ > _control_.packet_size_max) {                                                 \
628
        _packet_size_ -= _control_.packet_size_max - _control_.packet_size_min;                             \
629
        if (_packet_size_ > _control_.packet_size_max) {                                                    \
630
            _packet_size_ = _control_.packet_size_initial;                                                  \
631
        }                                                                                                   \
632
    }
633
 
634
/*}}}*/
635
/*{{{  Recovery support                                         */
636
 
637
// ----------------------------------------------------------------------------
638
// When things go wrong threads on either the host or the target may get
639
// locked up waiting for further communication that never happens, because
640
// the other side has already raised an error. Recovery is possible by
641
// performing an extra I/O operation. For example, if a thread on the
642
// target is blocked waiting on an OUT endpoint then recovery is possible
643
// by the host sending some data to that endpoint. Similarly if a thread
644
// on the host is blocked then recovery involves the target either sending
645
// or receiving some additional data. There are alternative approaches such
646
// as stalling endpoints, but making sure that the requested communication
647
// actually happens involves fewer dependencies on exactly how those
648
// operations behave.
649
 
650
typedef struct UsbTest_Recovery {
651
    int     endpoint;       // Top bit indicates direction, -1 indicates invalid
652
    int     protocol;
653
    int     size;
654
} UsbTest_Recovery;
655
 
656
static void
657
pack_usbtest_recovery(UsbTest_Recovery* recovery, unsigned char* buffer, int* index)
658
{
659
    pack_int(recovery->endpoint, buffer, index);
660
    pack_int(recovery->protocol, buffer, index);
661
    pack_int(recovery->size,     buffer, index);
662
}
663
 
664
static void
665
unpack_usbtest_recovery(UsbTest_Recovery* recovery, unsigned char* buffer, int *index)
666
{
667
    recovery->endpoint  = unpack_int(buffer, index);
668
    recovery->protocol  = unpack_int(buffer, index);
669
    recovery->size      = unpack_int(buffer, index);
670
}
671
 
672
static void
673
usbtest_recovery_reset(UsbTest_Recovery* recovery)
674
{
675
    recovery->endpoint  = -1;
676
    recovery->protocol  = 0;
677
    recovery->size      = 0;
678
}
679
 
680
/*}}}*/

powered by: WebSVN 2.1.0

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