📄 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 HOSTstatic voidpack_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 TARGETstatic voidunpack_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, receivestypedef 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 HOSTstatic voidpack_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 TARGETstatic voidunpack_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 voidpack_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 voidunpack_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 voidusbtest_recovery_reset(UsbTest_Recovery* recovery){ recovery->endpoint = -1; recovery->protocol = 0; recovery->size = 0;}/*}}}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -