USB设备的传输方式主要有四种:控制传输(Control Transfer)、中断传输(Interrupt Transfer)、批量传输(Bulk Transfer)和实时传输(Isochronous Transfer)。
具体内容可以参考https://blog.youkuaiyun.com/ljr1433223/article/details/130049625
libusb 1.0 API中的数据传输接口都是双向的,也就是说不分读写都是使用相同的函数。唯一的区别在于Request type或者端口地址。当它的最高位是0,就表示这次传输的是主机到设备的,主机角度来说就是写操作;反之是1的话就是设备到主机的,主机角度来说就是读操作。这是libusb 1.0 API传输函数的特点。
1. 控制传输(Control Transfer)
控制传输是USB必备的传输方式,它用于传输Control Setup包。它一般用于获取设备信息、状态,选择设备配置等的一系列命令式工作。关于Control Setup包的定义,可参考https://blog.youkuaiyun.com/wdsfup/article/details/49945205。
因为libusb API已经实现了一套获取USB设备信息的接口(具体可查看前面“ USB设备的基本操作”这一节),所以一般我们不用直接实现控制传输。只有在实现特定设备的特定控制命令时,比如获取PS3、XBOX主机的基本信息,才会需要自己实现控制传输。
libusb使用函数libusb_control_transfer来实现控制传输。函数定义如下:
int libusb_control_transfer (
libusb_device_handle *dev_handle,
uint8_t bmRequestType,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
unsigned char *data,
uint16_t wLength,
unsigned int timeout)
其中:
dev_handle:为上一节“USB设备的打开与关闭”中介绍的获取的USB设备句柄,后续不再赘述
bmRequestType: 为Control Setup包的request type部分。libusb有预定义了枚举类型来表示其中的传输方向,设备种类和接受者。传输方向可以用libusb_endpoint_direction类型,设备种类可以使用libusb_request_type类型,接受者可以使用libusb_request_recipient。所以,如果想要构建Get_Configuration命令的Request type,可以使用LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE这一组合
bRequest: 为Control Setup包的request命令。可以使用libusb_standard_request类型表示。比如:Get_Configuration命令可用LIBUSB_REQUEST_GET_CONFIGURATION
wValue: 为Control Setup包的value部分,该值需要根据Request命令设定相应的值,可以参考参考链接中的相关内容进行设定。
wIndex: 为Control Setup包的index部分,设置方式和wValue类似
data:为额外数据的buffer指针,比如设置和获取的Descriptor的字符串数据。
wLength:为额外数据buffer的最大长度。
timeout: 为发送此命令的超时时间,单位为ms。永远等待设成0即可。超时发生时,函数返回LIBUSB_ERROR_TIMEOUT错误
返回值:成功时返回传输数据的实际长度,一般大于0。失败时返回小于0的LIBUSB_ERROR_XXX错误码
例程如下,例程中实现了接口libusb_get_configuration的相同功能
bool GetConfigurationManual() {
if (mDevHandle == nullptr) {
LOGE("Failed to transfer control packet as device isn't initialized properly");
return false;
}
u8 data[256] = {0};
int ret = libusb_control_transfer(mDevHandle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
LIBUSB_REQUEST_GET_CONFIGURATION,
0, 0, data, sizeof(data), 100);
if (ret < 0) {
LOGE("Failed to transfer control packet, error: %d", ret);
return false;
}
LOGD("Got Configuration data: %s", bufferToString(data, (size_t)ret).c_str());
return true;
}
2. 中断传输(Interrupt Transfer)
中断传输采用轮询的方式进行数据的收发。它一般用于单次传输数据量较少,但数据传输频次较多的环境。它的传输优先级比较高,时效性比较好。所以,鼠标和键盘信号的传输方式就是中断传输。
libusb使用函数libusb_interrupt_transfer来实现中断传输。函数定义如下:
int libusb_interrupt_transfer (
libusb_device_handle *dev_handle,
unsigned char endpoint,
unsigned char *data,
int length,
int *transferred,
unsigned int timeout)
其中:
endpoint:为端口地址,可以通过在“USB设备的基本操作”一节中描述的获取USB Configuration信息的方式来获取。它就是endpoint->bEndpointAddress的值。当然如果根据产品Spec知道其Address,也可以直接设置。该值的最高位为0表明它是只写端口,为1表示它是只读端口
data: 为待发送或接收数据的buffer指针
length:为待发送或接收数据的buffer的最大长度
transferred:表示实际发送或接收数据的长度
timeout: 表示传输数据的超时时间,单位为ms。永远等待设成0即可。超时发生时,函数返回LIBUSB_ERROR_TIMEOUT错误
返回值:成功时返回LIBUSB_SUCCESS,否则返回小于0的LIBUSB_EEROR_XXX错误码
注意:不管发送还是接收,数据buffer的长度必须等于endpoint->wMaxPacketSize所规定的最大长度
例程如下:
int InterruptTransPkt(u8 ep, u8* buffer, int length, u32 timeout) {
if (mDevHandle == nullptr) {
LOGE("Failed to transfer packet as device isn't initialized properly");
return LIBUSB_ERROR_OTHER;
}
int actualLength = 0;
int ret = libusb_interrupt_transfer(mDevHandle, ep, buffer, length, &actualLength, timeout);
if (ret != LIBUSB_SUCCESS) {
if (ret == LIBUSB_ERROR_TIMEOUT && actualLength > 0) {
return actualLength;
}
LOGE("Failed to transfer package, error: %d", ret);
return ret;
}
return actualLength;
}
3. 批量传输(Bulk Transfer)
批量传输主要应用在单次传输大量数据的时候,它的时效性较差,主要用于对延时不敏感的情况。比如:U盘数据的传输就是批量传输。
libusb使用函数libusb_bulk_transfer来实现批量传输。函数定义如下:
int libusb_bulk_transfer (
libusb_device_handle *dev_handle,
unsigned char endpoint,
unsigned char *data,
int length,
int *transferred,
unsigned int timeout)
它的参数和中断传输函数类似,其中:
endpoint:为端口地址,获取方式类似中断传输
data: 为待发送或接收数据的buffer指针。buffer大小同样也需要设定为endpoint->wMaxPacketSize所规定的最大长度
length:为待发送或接收数据的buffer的最大长度
transferred:表示实际发送或接收数据的长度
timeout: 表示传输数据的超时时间,单位为ms。永远等待设成0即可。超时发生时,函数返回LIBUSB_ERROR_TIMEOUT错误
返回值:成功时返回LIBUSB_SUCCESS,否则返回小于0的LIBUSB_EEROR_XXX错误码
因为批量传输函数和中断传输函数类似,例程可参考中断传输的例子。
4. 实时传输(Isochronous Transfer)
不同于上述三种传输方式,实时传输并不保证传输数据的准确性,有点类似网络传输的UDP传输。但是它具有最好的时效性,所以通常用于传输摄像头捕获的视频或者给音响传输音频数据。
因为实时传输需要进行异步操作,所以libusb并没有提供同步模式下的函数。如果需要实现实时传输必须使用libusb数据传输的异步模式。这会在下一节详细描述。
1万+



被折叠的 条评论
为什么被折叠?



