记一次libusb库函数“libusb_bulk_transfer”的调用关系追踪

本文详细追踪了在使用libusb库函数libusb_bulk_transfer从USB设备读取数据时遇到的问题,涉及libusb库内部调用、USB设备文件节点、驱动层和HCD的交互,最终定位到硬件获取数据失败。

记一次libusb库函数“libusb_bulk_transfer”的调用关系追踪

一次使用libusb库函数“libusb_bulk_transfer”对外部USB设备进行读取数据的时候,出现了无数据返回的情况,但是使用USB分析仪,看到USB总线是进行了一次完整的IN令牌的transfer,如下图,感觉像是中间某一个节点没有将收到的device数据包返回上来,所以对代码进行下追踪,定位下问题大致位置。
在这里插入图片描述
这里记录下追踪到的函数调用关系:

libusb库内部调用关系

先看下大致调用流程:

> libusb_bulk_transfer(sync.c)
----> do_sync_bulk_transfer(sync.c)
--------> libusb_submit_transfer(io.c)
------------> usbi_backend->submit_transfer(core.c)
------------> linux_usbfs_backend.submit_transfer(linux_usbfs.c)
------------> op_submit_transfer(linux_usbfs.c)
----------------> submit_bulk_transfer(linux_usbfs.c)
--------------------> ioctl

可以看到,最终实际是调用到了系统的“ioctl”函数。
简单分析一下:

  1. do_sync_bulk_transfer(sync.c)中有两个重要的函数,如下:
static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
	unsigned char endpoint, unsigned char *buffer, int length,
	int *transferred, unsigned int timeout, unsigned char type)
{
   
   
	struct libusb_transfer *transfer = libusb_alloc_transfer(0);
	int completed = 0;
	int r;

	if (!transfer)
		return LIBUSB_ERROR_NO_MEM;
	//这个函数用来填充一个用于bulk传输的struct libusb_transfer
	libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length,
		bulk_transfer_cb, &completed, timeout);
	transfer->type = type;
	//这里提交上面填充好的transfer
	r = libusb_submit_transfer(transfer);
	if (r < 0) {
   
   
		libusb_free_transfer(transfer);
		return r;
	}

	......

	libusb_free_transfer(transfer);
	return r;
}
  1. libusb_submit_transfer(io.c)会调用不同平台的usbi_backend->submit_transfer,如下:
int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
{
   
   
	struct libusb_context *ctx = TRANSFER_CTX(transfer);
	struct usbi_transfer *itransfer =
		LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
	int r;
	int first;

	......

	first = add_to_flying_list(itransfer);
	//根据编译平台的不同,调用对应平台的 struct usbi_os_backend 成员 submit_transfer
	r = usbi_backend->submit_transfer(itransfer);
	if (r) {
   
   
		usbi_mutex_lock(&ctx->flying_transfers_lock);
		list_del(&itransfer->list);
		usbi_mutex_unlock(&ctx->flying_transfers_lock);
	}

	......

out:
	usbi_mutex_unlock(&itransfer->lock);
	return r;
}

不同平台的区分在core.c文件,如下:

#if defined(OS_LINUX)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值