📄 common.c
字号:
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 + -