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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [io/] [usb/] [slave/] [v2_0/] [tests/] [common.c] - Blame information for rev 174

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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