📄 common.c
字号:
/*{{{ Banner */
/*=================================================================
//
// common.c
//
// USB testing - code common to host and target
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// This module contains some definitions and functions that are common to
// both the host and target side of USB testing, for example filling in
// a buffer with well-known data and validating the contents at the other end.
// The module is #include'd by other code rather than compiled separately,
// which simplifies the build process.
//
// Author(s): bartv
// Date: 2001-08-14
//####DESCRIPTIONEND####
//==========================================================================
*/
/*}}}*/
/*{{{ Simple data pack and unpack operations */
// ----------------------------------------------------------------------------
// Utilities to pack and unpack data into buffers.
//
// Integers are transferred with 32 bits of precision, irrespective
// of the capabilities of either target and host.
static inline void
pack_int(int datum, unsigned char* buffer, int* index_ptr)
{
int index = *index_ptr;
buffer[index++] = (datum >> 0) & 0x0FF;
buffer[index++] = (datum >> 8) & 0x0FF;
buffer[index++] = (datum >> 16) & 0x0FF;
buffer[index++] = (datum >> 24) & 0x0FF;
*index_ptr = index;
}
static inline int
unpack_int(unsigned char* buffer, int* index_ptr)
{
int index = *index_ptr;
int result;
result = (buffer[index++] << 0);
result |= (buffer[index++] << 8);
result |= (buffer[index++] << 16);
result |= (buffer[index++] << 24);
*index_ptr = index;
return result;
}
/*}}}*/
/*{{{ Buffer data and validation */
// ----------------------------------------------------------------------------
// The data required for a given test. For some test cases, for
// example when trying to achieve maximum throughput, it does not
// matter what data is transferred. For other tests it is important to
// validate that the data sent and received match up, and there should
// be some control over the actual data: some tests might want to send
// a long sequence of byte 0, while others want to send more random data
// for which a simple random number generator is useful.
//
// Exactly the same routines are used on both host and target to fill in
// and check buffers, and they are sufficiently simple that the routines
// should get compiled in compatible ways.
//
// There is no support at present for sending specific data, e.g. a
// specific ethernet packet that appears to be causing problems. Knowledge
// of specific data cannot be compiled into the test code, so the only
// way to implement something like this would be to transfer the
// problematical data over the USB bus in order to determine whether or
// not the bus is capable of reliably transferring this data. That is
// not entirely impossible (checksums, use of alternative endpoints),
// but it is not implemented.
//
// An alternative approach would be to support a bounce operation
// involving both an IN and an OUT endpoint, doing validation only on
// the host. Again that is not yet implemented.
//
// The byte_fill and int_fill options are actually redundant because the
// same effect can be achieved using a multiplier of 1 and an increment
// of 0, but they can be implemented much more efficiently so may be
// useful for benchmarks.
typedef enum usbtestdata {
usbtestdata_none = 0, // There is nothing useful in the data
usbtestdata_bytefill = 1, // The data consists of a single byte, repeated
usbtestdata_wordfill = 2, // Or a single integer
usbtestdata_byteseq = 3, // Or a pseudo-random sequence (a * seed) + b
usbtestdata_wordseq = 4 // as either bytes or integers
} usbtestdata;
typedef struct UsbTestData {
usbtestdata format;
int seed;
int multiplier; // 1103515245
int increment; // 12345
int transfer_seed_multiplier;
int transfer_seed_increment;
int transfer_multiplier_multiplier;
int transfer_multiplier_increment;
int transfer_increment_multiplier;
int transfer_increment_increment;
} UsbTestData;
static void
usbtest_fill_buffer(UsbTestData* how, unsigned char* buffer, int length)
{
switch(how->format)
{
case usbtestdata_none:
return;
case usbtestdata_bytefill:
// Leave it to the system to optimise memset().
memset(buffer, (how->seed & 0x0FF), length);
break;
case usbtestdata_wordfill:
{
// The buffer may not be a multiple of four bytes, so the last entry is always
// zero'd.
int i;
int index = 0;
for (i = 0; i < (length / 4); i++) {
pack_int(how->seed, buffer, &index);
}
pack_int(0, buffer, &index);
break;
}
case usbtestdata_byteseq:
{
int i;
for (i = 0; i < length; i++) {
buffer[i] = (how->seed & 0x00FF);
how->seed *= how->multiplier;
how->seed += how->increment;
}
break;
}
case usbtestdata_wordseq:
{
int i;
int index = 0;
for (i = 0; i < (length / 4); i++) {
pack_int(how->seed, buffer, &index);
how->seed *= how->multiplier;
how->seed += how->increment;
}
pack_int(0, buffer, &index);
break;
}
}
// After each transfer update the seed, multiplier and increment
// ready for the next one.
how->seed *= how->transfer_seed_multiplier;
how->seed += how->transfer_seed_increment;
how->multiplier *= how->transfer_multiplier_multiplier;
how->multiplier += how->transfer_multiplier_increment;
how->increment *= how->transfer_increment_multiplier;
how->increment += how->transfer_increment_increment;
}
static int
usbtest_check_buffer(UsbTestData* how, unsigned char* buffer, int length)
{
int result = 1;
switch(how->format) {
case usbtestdata_none:
break;
case usbtestdata_bytefill:
{
int i;
result = 1;
for (i = 0; i < length; i++) {
if (buffer[i] != (how->seed & 0x00FF)) {
result = 0;
break;
}
}
break;
}
case usbtestdata_wordfill:
{
int i;
int index = 0;
for (i = 0; i < (length / 4); i++) {
int datum = unpack_int(buffer, &index);
if (datum != (how->seed & 0x0FFFFFFFF)) {
result = 0;
break;
}
}
for (i = 4 * i; result && (i < length); i++) {
if (0 != buffer[i]) {
result = 0;
break;
}
}
break;
}
case usbtestdata_byteseq:
{
int i;
for (i = 0; i < length; i++) {
if (buffer[i] != (how->seed & 0x00FF)) {
result = 0;
break;
}
how->seed *= how->multiplier;
how->seed += how->increment;
}
break;
}
case usbtestdata_wordseq:
{
int i;
int index = 0;
for (i = 0; i < (length / 4); i++) {
int datum = unpack_int(buffer, &index);
if (datum != (how->seed & 0x0FFFFFFFF)) {
result = 0;
break;
}
how->seed *= how->multiplier;
how->seed += how->increment;
}
for (i = 4 * i; result && (i < length); i++) {
if (0 != buffer[i]) {
result = 0;
break;
}
}
break;
}
}
// After each transfer update the seed, multiplier and increment
// ready for the next transfer.
how->seed *= how->transfer_seed_multiplier;
how->seed += how->transfer_seed_increment;
how->multiplier *= how->transfer_multiplier_multiplier;
how->multiplier += how->transfer_multiplier_increment;
how->increment *= how->transfer_increment_multiplier;
how->increment += how->transfer_increment_increment;
return result;
}
#ifdef HOST
static void
pack_usbtestdata(UsbTestData* data, unsigned char* buf, int* index)
{
pack_int((int)data->format, buf, index);
pack_int((int)data->seed, buf, index);
pack_int((int)data->multiplier, buf, index);
pack_int((int)data->increment, buf, index);
pack_int((int)data->transfer_seed_multiplier, buf, index);
pack_int((int)data->transfer_seed_increment, buf, index);
pack_int((int)data->transfer_multiplier_multiplier, buf, index);
pack_int((int)data->transfer_multiplier_increment, buf, index);
pack_int((int)data->transfer_increment_multiplier, buf, index);
pack_int((int)data->transfer_increment_increment, buf, index);
}
#endif
#ifdef TARGET
static void
unpack_usbtestdata(UsbTestData* data, unsigned char* buf, int* index)
{
data->format = (usbtestdata) unpack_int(buf, index);
data->seed = unpack_int(buf, index);
data->multiplier = unpack_int(buf, index);
data->increment = unpack_int(buf, index);
data->transfer_seed_multiplier = unpack_int(buf, index);
data->transfer_seed_increment = unpack_int(buf, index);
data->transfer_multiplier_multiplier= unpack_int(buf, index);
data->transfer_multiplier_increment = unpack_int(buf, index);
data->transfer_increment_multiplier = unpack_int(buf, index);
data->transfer_increment_increment = unpack_int(buf, index);
}
#endif
/*}}}*/
/*{{{ Testcase definitions */
// ----------------------------------------------------------------------------
// Definitions of the supported test cases. The actual implementations need
// to vary between host and target.
typedef enum usbtest {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -