📄 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 voidpack_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 intunpack_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 voidusbtest_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 intusbtest_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 HOSTstatic voidpack_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 TARGETstatic voidunpack_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 + -