⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 common.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*{{{  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 + -