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

📄 common.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
    usbtest_invalid     = 0,
    usbtest_bulk_out    = 1,
    usbtest_bulk_in     = 2,
    usbtest_control_in  = 3
} usbtest;

// What I/O mechanism should be used on the target to process data?
typedef enum usb_io_mechanism {
    usb_io_mechanism_usb    = 1,        // The low-level USB-specific API
    usb_io_mechanism_dev    = 2         // cyg_devio_cread() et al
} usb_io_mechanism;

// Bulk transfers. The same structure can be used for IN and OUT transfers.
// The endpoint number will be or'd with either USB_DIR_IN or USB_DIR_OUT,
// or the equivalent under eCos.
typedef struct UsbTest_Bulk {
    int                 number_packets;
    int                 endpoint;
    int                 tx_size;
    int                 tx_size_min;
    int                 tx_size_max;
    int                 tx_size_multiplier;
    int                 tx_size_divisor;
    int                 tx_size_increment;
    int                 rx_size;
    int                 rx_size_min;
    int                 rx_size_max;
    int                 rx_size_multiplier;
    int                 rx_size_divisor;
    int                 rx_size_increment;
    int                 rx_padding;
    int                 tx_delay;
    int                 tx_delay_min;
    int                 tx_delay_max;
    int                 tx_delay_multiplier;
    int                 tx_delay_divisor;
    int                 tx_delay_increment;
    int                 rx_delay;
    int                 rx_delay_min;
    int                 rx_delay_max;
    int                 rx_delay_multiplier;
    int                 rx_delay_divisor;
    int                 rx_delay_increment;
    usb_io_mechanism    io_mechanism;
    UsbTestData         data;
} UsbTest_Bulk;

#ifdef HOST
static void
pack_usbtest_bulk(UsbTest_Bulk* test, unsigned char* buffer, int* index)
{
    pack_int(test->number_packets,          buffer, index);
    pack_int(test->endpoint,                buffer, index);
    pack_int(test->tx_size,                 buffer, index);
    pack_int(test->tx_size_min,             buffer, index);
    pack_int(test->tx_size_max,             buffer, index);
    pack_int(test->tx_size_multiplier,      buffer, index);
    pack_int(test->tx_size_divisor,         buffer, index);
    pack_int(test->tx_size_increment,       buffer, index);
    pack_int(test->rx_size,                 buffer, index);
    pack_int(test->rx_size_min,             buffer, index);
    pack_int(test->rx_size_max,             buffer, index);
    pack_int(test->rx_size_multiplier,      buffer, index);
    pack_int(test->rx_size_divisor,         buffer, index);
    pack_int(test->rx_size_increment,       buffer, index);
    // There is no need to transfer the padding field. It is only of
    // interest on the host, and this message is being packed
    // for the target side.
    pack_int(test->tx_delay,                buffer, index);
    pack_int(test->tx_delay_min,            buffer, index);
    pack_int(test->tx_delay_max,            buffer, index);
    pack_int(test->tx_delay_multiplier,     buffer, index);
    pack_int(test->tx_delay_divisor,        buffer, index);
    pack_int(test->tx_delay_increment,      buffer, index);
    pack_int(test->rx_delay,                buffer, index);
    pack_int(test->rx_delay_min,            buffer, index);
    pack_int(test->rx_delay_max,            buffer, index);
    pack_int(test->rx_delay_multiplier,     buffer, index);
    pack_int(test->rx_delay_divisor,        buffer, index);
    pack_int(test->rx_delay_increment,      buffer, index);
    pack_int((int)test->io_mechanism,       buffer, index);
    pack_usbtestdata(&(test->data),         buffer, index);
}
#endif

#ifdef TARGET
static void
unpack_usbtest_bulk(UsbTest_Bulk* test, unsigned char* buffer, int* index)
{
    test->number_packets            = unpack_int(buffer, index);
    test->endpoint                  = unpack_int(buffer, index);
    test->tx_size                   = unpack_int(buffer, index);
    test->tx_size_min               = unpack_int(buffer, index);
    test->tx_size_max               = unpack_int(buffer, index);
    test->tx_size_multiplier        = unpack_int(buffer, index);
    test->tx_size_divisor           = unpack_int(buffer, index);
    test->tx_size_increment         = unpack_int(buffer, index);
    test->rx_size                   = unpack_int(buffer, index);
    test->rx_size_min               = unpack_int(buffer, index);
    test->rx_size_max               = unpack_int(buffer, index);
    test->rx_size_multiplier        = unpack_int(buffer, index);
    test->rx_size_divisor           = unpack_int(buffer, index);
    test->rx_size_increment         = unpack_int(buffer, index);
    test->tx_delay                  = unpack_int(buffer, index);
    test->tx_delay_min              = unpack_int(buffer, index);
    test->tx_delay_max              = unpack_int(buffer, index);
    test->tx_delay_multiplier       = unpack_int(buffer, index);
    test->tx_delay_divisor          = unpack_int(buffer, index);
    test->tx_delay_increment        = unpack_int(buffer, index);
    test->rx_delay                  = unpack_int(buffer, index);
    test->rx_delay_min              = unpack_int(buffer, index);
    test->rx_delay_max              = unpack_int(buffer, index);
    test->rx_delay_multiplier       = unpack_int(buffer, index);
    test->rx_delay_divisor          = unpack_int(buffer, index);
    test->rx_delay_increment        = unpack_int(buffer, index);
    test->io_mechanism              = (usb_io_mechanism) unpack_int(buffer, index);
    unpack_usbtestdata(&(test->data), buffer, index);
}
#endif

// A macro for moving on the next packet size. This also has to be shared between host
// and target, if the two got out of synch then testing would go horribly wrong.
//
// The new packet size is determined using a multiplier and increment,
// so to e.g. increase packet sizes by 4 bytes each time the
// multiplier would be 1 and the increment would be 4, or to double
// packet sizes the multiplier would be 2 and the increment would be
// 0. On underflow or overflow the code tries to adjust the packet size
// back to within the accepted range.

#define USBTEST_NEXT_TX_SIZE(_x_)                               \
    do {                                                        \
        _x_.tx_size *= _x_.tx_size_multiplier;                  \
        _x_.tx_size /= _x_.tx_size_divisor;                     \
        _x_.tx_size += _x_.tx_size_increment;                   \
        if (_x_.tx_size < _x_.tx_size_min) {                    \
            if (_x_.tx_size_min == _x_.tx_size_max) {           \
                _x_.tx_size = _x_.tx_size_min;                  \
            } else {                                            \
                int tmp  = _x_.tx_size_min - _x_.tx_size;       \
                tmp     %= _x_.tx_size_max - _x_.tx_size_min;   \
                _x_.tx_size = tmp + _x_.tx_size_min;            \
            }                                                   \
        } else if (_x_.tx_size > _x_.tx_size_max) {             \
            if (_x_.tx_size_min == _x_.tx_size_max) {           \
                _x_.tx_size = _x_.tx_size_max;                  \
            } else {                                            \
                int tmp  = _x_.tx_size - _x_.tx_size_max;       \
                tmp     %= _x_.tx_size_max - _x_.tx_size_min;   \
                _x_.tx_size = tmp + _x_.tx_size_min;            \
            }                                                   \
        }                                                       \
    } while ( 0 )

// A similar macro for moving on to the next receive size. This is less
// critical since care is taken to always receive at least the current
// tx size plus padding.
// Note that padding needs to be added by the calling code, not here,
// since padding is only applicable on the host-side and this macro
// is used on both host and target.
#define USBTEST_NEXT_RX_SIZE(_x_)                               \
    do {                                                        \
        _x_.rx_size *= _x_.rx_size_multiplier;                  \
        _x_.rx_size /= _x_.rx_size_divisor;                     \
        _x_.rx_size += _x_.rx_size_increment;                   \
        if (_x_.rx_size < _x_.rx_size_min) {                    \
            if (_x_.rx_size_min == _x_.rx_size_max) {           \
                _x_.rx_size = _x_.rx_size_min;                  \
            } else {                                            \
                int tmp  = _x_.rx_size_min - _x_.rx_size;       \
                tmp     %= _x_.rx_size_max - _x_.rx_size_min;   \
                _x_.rx_size = tmp + _x_.rx_size_min;            \
            }                                                   \
        } else if (_x_.rx_size > _x_.rx_size_max) {             \
            if (_x_.rx_size_min == _x_.rx_size_max) {           \
                _x_.rx_size = _x_.rx_size_max;                  \
            } else {                                            \
                int tmp  = _x_.rx_size - _x_.rx_size_max;       \
                tmp     %= _x_.rx_size_max - _x_.rx_size_min;   \
                _x_.rx_size = tmp + _x_.rx_size_min;            \
            }                                                   \
        }                                                       \
    } while ( 0 )

// And a macro for adjusting the transmit delay.
#define USBTEST_NEXT_TX_DELAY(_x_)                              \
    do {                                                        \
        _x_.tx_delay *= _x_.tx_delay_multiplier;                \
        _x_.tx_delay /= _x_.tx_delay_divisor;                   \
        _x_.tx_delay += _x_.tx_delay_increment;                 \
        if (_x_.tx_delay < _x_.tx_delay_min) {                  \
            if (_x_.tx_delay_min == _x_.tx_delay_max) {         \
                _x_.tx_delay = _x_.tx_delay_min;                \
            } else {                                            \
                int tmp  = _x_.tx_delay_min - _x_.tx_delay;     \
                tmp     %= _x_.tx_delay_max - _x_.tx_delay_min; \
                _x_.tx_delay = tmp + _x_.tx_delay_min;          \
            }                                                   \
        } else if (_x_.tx_delay > _x_.tx_delay_max) {           \
            if (_x_.tx_delay_min == _x_.tx_delay_max) {         \
                _x_.tx_delay = _x_.tx_delay_max;                \
            } else {                                            \
                int tmp  = _x_.tx_delay - _x_.tx_delay_max;     \
                tmp     %= _x_.tx_delay_max - _x_.tx_delay_min; \
                _x_.tx_delay = tmp + _x_.tx_delay_min;          \
            }                                                   \
        }                                                       \
    } while ( 0 )

#define USBTEST_NEXT_RX_DELAY(_x_)                              \
    do {                                                        \
        _x_.rx_delay *= _x_.rx_delay_multiplier;                \
        _x_.rx_delay /= _x_.rx_delay_divisor;                   \
        _x_.rx_delay += _x_.rx_delay_increment;                 \
        if (_x_.rx_delay < _x_.rx_delay_min) {                  \
            if (_x_.rx_delay_min == _x_.rx_delay_max) {         \
                _x_.rx_delay = _x_.rx_delay_min;                \
            } else {                                            \
                int tmp  = _x_.rx_delay_min - _x_.rx_delay;     \
                tmp     %= _x_.rx_delay_max - _x_.rx_delay_min; \
                _x_.rx_delay = tmp + _x_.rx_delay_min;          \
            }                                                   \
        } else if (_x_.rx_delay > _x_.rx_delay_max) {           \
            if (_x_.rx_delay_min == _x_.rx_delay_max) {         \
                _x_.rx_delay = _x_.rx_delay_max;                \
            } else {                                            \
                int tmp  = _x_.rx_delay - _x_.rx_delay_max;     \
                tmp     %= _x_.rx_delay_max - _x_.rx_delay_min; \
                _x_.rx_delay = tmp + _x_.rx_delay_min;          \
            }                                                   \
        }                                                       \
    } while ( 0 )

#define USBTEST_BULK_NEXT(_bulk_)                               \
    USBTEST_NEXT_TX_SIZE(_bulk_);                               \
    USBTEST_NEXT_RX_SIZE(_bulk_);                               \
    USBTEST_NEXT_TX_DELAY(_bulk_);                              \
    USBTEST_NEXT_RX_DELAY(_bulk_);

// Control transfers, receives
typedef struct UsbTest_ControlIn {
    int         number_packets;
    int         packet_size_initial;
    int         packet_size_min;
    int         packet_size_max;
    int         packet_size_multiplier;
    int         packet_size_increment;
    UsbTestData data;
} UsbTest_ControlIn;

#ifdef HOST
static void
pack_usbtest_control_in(UsbTest_ControlIn* test, unsigned char* buffer, int* index)
{
    pack_int(test->number_packets,          buffer, index);
    pack_int(test->packet_size_initial,     buffer, index);
    pack_int(test->packet_size_min,         buffer, index);
    pack_int(test->packet_size_max,         buffer, index);
    pack_int(test->packet_size_multiplier,  buffer, index);
    pack_int(test->packet_size_increment,   buffer, index);
    pack_usbtestdata(&(test->data),         buffer, index);
}
#endif

#ifdef TARGET
static void
unpack_usbtest_control_in(UsbTest_ControlIn* test, unsigned char* buffer, int* index)
{
    test->number_packets            = unpack_int(buffer, index);
    test->packet_size_initial       = unpack_int(buffer, index);
    test->packet_size_min           = unpack_int(buffer, index);
    test->packet_size_max           = unpack_int(buffer, index);
    test->packet_size_multiplier    = unpack_int(buffer, index);
    test->packet_size_increment     = unpack_int(buffer, index);
    unpack_usbtestdata(&(test->data), buffer, index);
}
#endif

// For now control packet sizes are adjusted in exactly the same way as bulk transfers.
#define USBTEST_CONTROL_NEXT_PACKET_SIZE(_packet_size_, _control_)                                          \
    _packet_size_ = (_packet_size_ * _control_.packet_size_multiplier) + _control_.packet_size_increment;   \
    if (_packet_size_ < _control_.packet_size_min) {                                                        \
        _packet_size_ += _control_.packet_size_max - _control_.packet_size_min;                             \
        if (_packet_size_ < _control_.packet_size_min) {                                                    \
            _packet_size_ = _control_.packet_size_initial;                                                  \
        }                                                                                                   \
    } else if (_packet_size_ > _control_.packet_size_max) {                                                 \
        _packet_size_ -= _control_.packet_size_max - _control_.packet_size_min;                             \
        if (_packet_size_ > _control_.packet_size_max) {                                                    \
            _packet_size_ = _control_.packet_size_initial;                                                  \
        }                                                                                                   \
    }

/*}}}*/
/*{{{  Recovery support                                         */

// ----------------------------------------------------------------------------
// When things go wrong threads on either the host or the target may get
// locked up waiting for further communication that never happens, because
// the other side has already raised an error. Recovery is possible by
// performing an extra I/O operation. For example, if a thread on the
// target is blocked waiting on an OUT endpoint then recovery is possible
// by the host sending some data to that endpoint. Similarly if a thread
// on the host is blocked then recovery involves the target either sending
// or receiving some additional data. There are alternative approaches such
// as stalling endpoints, but making sure that the requested communication
// actually happens involves fewer dependencies on exactly how those
// operations behave.

typedef struct UsbTest_Recovery {
    int     endpoint;       // Top bit indicates direction, -1 indicates invalid
    int     protocol;
    int     size;
} UsbTest_Recovery;

static void
pack_usbtest_recovery(UsbTest_Recovery* recovery, unsigned char* buffer, int* index)
{
    pack_int(recovery->endpoint, buffer, index);
    pack_int(recovery->protocol, buffer, index);
    pack_int(recovery->size,     buffer, index);
}

static void
unpack_usbtest_recovery(UsbTest_Recovery* recovery, unsigned char* buffer, int *index)
{
    recovery->endpoint  = unpack_int(buffer, index);
    recovery->protocol  = unpack_int(buffer, index);
    recovery->size      = unpack_int(buffer, index);
}

static void
usbtest_recovery_reset(UsbTest_Recovery* recovery)
{
    recovery->endpoint  = -1;
    recovery->protocol  = 0;
    recovery->size      = 0;
}

/*}}}*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -