06_libusb的使用: 给API函数增加了中文件注释

This commit is contained in:
weidongshan
2022-09-17 17:59:42 +08:00
parent 1bea21f668
commit b1e7d69ca4

View File

@@ -45,8 +45,8 @@ unsigned char data[4];
int actual_length;
int r = libusb_bulk_transfer(dev_handle, LIBUSB_ENDPOINT_IN, data, sizeof(data), &actual_length, 0);
if (r == 0 && actual_length == sizeof(data)) {
// results of the transaction can now be found in the data buffer
// parse them here and report button press
// 接收到的数据保存在data数组里
// 解析这些数据就可以知道按键状态
} else {
error();
}
@@ -61,18 +61,17 @@ if (r == 0 && actual_length == sizeof(data)) {
### 2.2 初始化
```c
/** \ingroup libusb_lib
* Initialize libusb. This function must be called before calling any other
* libusb function.
/**
* 初始化libusb这个函数必须先与其他libusb的函数执行
*
* If you do not provide an output location for a context pointer, a default
* context will be created. If there was already a default context, it will
* be reused (and nothing will be initialized/reinitialized).
* 如果传入NULL那么函数内部会穿件一个默认的context
* 如果已经创建过默认的context这个context会被重新使用(不会重新初始化它)
*
* \param ctx Optional output location for context pointer.
* Only valid on return code 0.
* \returns 0 on success, or a LIBUSB_ERROR code on failure
* \see libusb_contexts
* 参数:
* ctx : context pointer的位置也可以传入NULL
* 返回值
* 0 - 成功
* 负数 - 失败
*/
int API_EXPORTED libusb_init(libusb_context **ctx);
```
@@ -87,24 +86,18 @@ int API_EXPORTED libusb_init(libusb_context **ctx);
```c
/** @ingroup libusb_dev
* Returns a list of USB devices currently attached to the system. This is
* your entry point into finding a USB device to operate.
* 返回一个listlist里含有当前系统中所有的USB设备
*
* You are expected to unreference all the devices when you are done with
* them, and then free the list with libusb_free_device_list(). Note that
* libusb_free_device_list() can unref all the devices for you. Be careful
* not to unreference a device you are about to open until after you have
* opened it.
* 我们一般会在list里寻找需要访问的设备找到之后使用libusb_open函数打开它
* 然后调用libusb_free_device_list释放list
*
* This return value of this function indicates the number of devices in
* the resultant list. The list is actually one element larger, as it is
* NULL-terminated.
* 这个函数的返回值表示list中有多少个设备
* list的最后一项是NULL
*
* \param ctx the context to operate on, or NULL for the default context
* \param list output location for a list of devices. Must be later freed with
* libusb_free_device_list().
* \returns the number of devices in the outputted list, or any
* \ref libusb_error according to errors encountered by the backend.
* 参数:
* ctx : context
* list : output location for a list of devices, 最后必须调用libusb_free_device_list()来释放它
* 返回值: list中设备的个数, 或错误值
*/
ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx,
libusb_device ***list);
@@ -114,11 +107,12 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx,
```c
/** \ingroup libusb_dev
* Frees a list of devices previously discovered using
* libusb_get_device_list(). If the unref_devices parameter is set, the
* reference count of each device in the list is decremented by 1.
* \param list the list to free
* \param unref_devices whether to unref the devices in the list
* 前面使用libusb_get_device_list()获得了设备list,
* 使用完后要调用libusb_free_device_list()释放这个list
* 如果参数unref_devices为1, 则list中每个设备的引用计数值减小1
* 参数:
* list : 要释放的设备list
* unref_devices : 是否要将设备的引用计数减1
*/
void API_EXPORTED libusb_free_device_list(libusb_device **list,
int unref_devices);
@@ -130,23 +124,21 @@ void API_EXPORTED libusb_free_device_list(libusb_device **list,
```c
/** \ingroup libusb_dev
* Open a device and obtain a device handle. A handle allows you to perform
* I/O on the device in question.
* 打开一个设备并得到它的句柄, 以后进行IO操作时都是使用句柄
*
* Internally, this function adds a reference to the device and makes it
* available to you through libusb_get_device(). This reference is removed
* during libusb_close().
* 使用libusb_get_device()函数可以得到设备的list,
* 从list里确定你要访问的设备后, 使用libusb_open()去打开它。
* libusb_open()函数内部会增加此设备的引用计数, 使用完毕后要调用libusb_close()减小引用计数。
*
* This is a non-blocking function; no requests are sent over the bus.
*
* \param dev the device to open
* \param dev_handle output location for the returned device handle pointer. Only
* populated when the return code is 0.
* \returns 0 on success
* \returns \ref LIBUSB_ERROR_NO_MEM on memory allocation failure
* \returns \ref LIBUSB_ERROR_ACCESS if the user has insufficient permissions
* \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
* \returns another LIBUSB_ERROR code on other failure
* 参数:
* dev : 要打开的设备
* dev_handle : 输出参数, 用来保存句柄
* 返回值:
* 0 - 成功
* LIBUSB_ERROR_NO_MEM : 缺少内存
* LIBUSB_ERROR_ACCESS : 权限不足
* LIBUSB_ERROR_NO_DEVICE : 这个设备未连接
* 其他错误 : 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_open(libusb_device *dev,
libusb_device_handle **dev_handle);
@@ -158,15 +150,12 @@ int API_EXPORTED libusb_open(libusb_device *dev,
```c
/** \ingroup libusb_dev
* Close a device handle. Should be called on all open handles before your
* application exits.
* 关闭设备句柄, 在程序退出之前应该使用它去关闭已经打开的句柄
*
* Internally, this function destroys the reference that was added by
* libusb_open() on the given device.
* 设备的引用计数在前面被libusb_open()函数增加了。
* libusb_close()函数的内部,它会减小设备的引用计数。
*
* This is a non-blocking function; no requests are sent over the bus.
*
* \param dev_handle the device handle to close
* 参数: dev_handle - 句柄
*/
void API_EXPORTED libusb_close(libusb_device_handle *dev_handle);
```
@@ -181,21 +170,23 @@ libusb_open_device_with_vid_pid函数原型如下
```c
/** \ingroup libusb_dev
* Convenience function for finding a device with a particular
* <tt>idVendor</tt>/<tt>idProduct</tt> combination. This function is intended
* for those scenarios where you are using libusb to knock up a quick test
* application - it allows you to avoid calling libusb_get_device_list() and
* worrying about traversing/freeing the list.
* 打开设备的常规做法是使用libusb_get_device_list()得到设备list
* 然后遍历list找到设备
* 接着使用libusb_open()函数得到句柄
*
* 如果知道USB设备的VID、PID那么可以使用libusb_open_device_with_vid_pid()函数快速打开它,得到句柄。
*
* 这个函数有一个缺点: 如果系统中有多个ID相同的设备你只能打开第1个设备
*
* This function has limitations and is hence not intended for use in real
* applications: if multiple devices have the same IDs it will only
* give you the first one, etc.
*
* \param ctx the context to operate on, or NULL for the default context
* \param vendor_id the idVendor value to search for
* \param product_id the idProduct value to search for
* \returns a device handle for the first found device, or NULL on error
* or if the device could not be found. */
* 参数:
* ctx : context, 或者传入NULL以使用默认的context
* vendor_id : 厂家ID
* product_id : 产品ID
*
* 返回值:
* 句柄 - 找到的第1个设备的句柄
* NULL - 没有找到设备
*/
DEFAULT_VISIBILITY
libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid(
libusb_context *ctx, uint16_t vendor_id, uint16_t product_id);
@@ -205,6 +196,8 @@ libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid(
### 2.6 detach/attach驱动
#### 2.6.1 两种方法
使用libusb访问USB设备时需要先移除(detach)设备原来的驱动程序,然后安装(attach)libusb专用的驱动程序。有两种办法
* 方法1
@@ -230,28 +223,30 @@ libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid(
#### 2.6.2 函数原型
函数`libusb_detach_kernel_driver`原型如下:
```c
* Detach a kernel driver from an interface. If successful, you will then be
* able to claim the interface and perform I/O.
/** \ingroup libusb_dev
* 给USB设备的接口(interface)移除驱动程序. If successful, you will then be
* 移除原来的驱动后才能"claim the interface"、执行IO操作
*
* This functionality is not available on Windows.
* 实际上libusb会给这个接口安装一个特殊的内核驱动,
* 所以本函数"移除驱动"是移除其他驱动,不是移除这个特殊的驱动。
* 若干这个接口已经安装了这个特殊的驱动本函数会返回LIBUSB_ERROR_NOT_FOUND.
*
* Note that libusb itself also talks to the device through a special kernel
* driver, if this driver is already attached to the device, this call will
* not detach it and return \ref LIBUSB_ERROR_NOT_FOUND.
*
* \param dev_handle a device handle
* \param interface_number the interface to detach the driver from
* \returns 0 on success
* \returns \ref LIBUSB_ERROR_NOT_FOUND if no kernel driver was active
* \returns \ref LIBUSB_ERROR_INVALID_PARAM if the interface does not exist
* \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
* \returns \ref LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality
* is not available
* \returns another LIBUSB_ERROR code on other failure
* \see libusb_kernel_driver_active()
* 参数:
* dev_handle - 设备句柄
* interface_number - 哪一个接口
*
* 返回值:
* 0 - 成功
* LIBUSB_ERROR_NOT_FOUND - 这个接口没有安装其他驱动
* LIBUSB_ERROR_INVALID_PARAM - 没有这个接口
* LIBUSB_ERROR_NO_DEVICE - 这个设备未连接
* LIBUSB_ERROR_NOT_SUPPORTED - 系统不支持此操作, 比如Windows
* 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle,
int interface_number);
@@ -263,32 +258,27 @@ int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle,
```c
/** \ingroup libusb_dev
* Claim an interface on a given device handle. You must claim the interface
* you wish to use before you can perform I/O on any of its endpoints.
* libusb使用内核里一个特殊的驱动程序
* libusb_claim_interface()函数就是给某个usb接口安装这个特殊的驱动程序
* 在使用libusb的函数执行IO操作之前必须调用本函数。
*
* It is legal to attempt to claim an already-claimed interface, in which
* case libusb just returns 0 without doing anything.
* 你可以给"已经claim过的接口"再次调用本函数它直接返回0。
*
* If auto_detach_kernel_driver is set to 1 for <tt>dev</tt>, the kernel driver
* will be detached if necessary, on failure the detach error is returned.
* 如果这个接口的auto_detach_kernel_driver被设置为1
* libusb_claim_interface()函数会先移除其他驱动。
*
* Claiming of interfaces is a purely logical operation; it does not cause
* any requests to be sent over the bus. Interface claiming is used to
* instruct the underlying operating system that your application wishes
* to take ownership of the interface.
* 本函数时纯粹的逻辑操作只是替换接口的驱动程序而已不会导致USB硬件传输。
*
* This is a non-blocking function.
* 参数:
* dev_handle - 句柄, 表示USB设备
* interface_number - 接口
*
* \param dev_handle a device handle
* \param interface_number the <tt>bInterfaceNumber</tt> of the interface you
* wish to claim
* \returns 0 on success
* \returns \ref LIBUSB_ERROR_NOT_FOUND if the requested interface does not exist
* \returns \ref LIBUSB_ERROR_BUSY if another program or driver has claimed the
* interface
* \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
* \returns a LIBUSB_ERROR code on other failure
* \see libusb_set_auto_detach_kernel_driver()
* 返回值:
* 0 - 成功
* LIBUSB_ERROR_NOT_FOUND - 没有这个接口
* LIBUSB_ERROR_BUSY - 其他APP或者驱动正在使用这个接口
* LIBUSB_ERROR_NO_DEVICE - 设备未连接
* 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle,
int interface_number);
@@ -300,23 +290,23 @@ int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle,
```c
/** \ingroup libusb_dev
* Release an interface previously claimed with libusb_claim_interface(). You
* should release all claimed interfaces before closing a device handle.
* 前面使用libusb_claim_interface()给接口安装了给libusb使用的特殊驱动程序,
* 使用完毕后在调用libusb_close()关闭句柄之前,
* 可以调用libusb_release_interface()卸载特殊驱动程序
* 如果设备的auto_detach_kernel_driver为1还会重新安装普通驱动程序
*
* 这是一个阻塞函数, 它会给USB设备发送一个请求: SET_INTERFACE control,
* 用来把接口的状态复位到第1个setting(the first alternate setting)
*
* This is a blocking function. A SET_INTERFACE control request will be sent
* to the device, resetting interface state to the first alternate setting.
*
* If auto_detach_kernel_driver is set to 1 for <tt>dev</tt>, the kernel
* driver will be re-attached after releasing the interface.
*
* \param dev_handle a device handle
* \param interface_number the <tt>bInterfaceNumber</tt> of the
* previously-claimed interface
* \returns 0 on success
* \returns \ref LIBUSB_ERROR_NOT_FOUND if the interface was not claimed
* \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
* \returns another LIBUSB_ERROR code on other failure
* \see libusb_set_auto_detach_kernel_driver()
* 参数:
* dev_handle - 设备句柄
* interface_number - 哪个接口
*
* 返回值:
* 0 - 成功
* LIBUSB_ERROR_NOT_FOUND - 这个接口没有被claim(没有安装特殊的驱动程序)
* LIBUSB_ERROR_NO_DEVICE - 设备未连接
* 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle,
int interface_number);
@@ -326,54 +316,46 @@ int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle,
### 2.7 描述符相关函数
**获得设备描述符**
#### 2.7.1 获得设备描述符
```c
/** \ingroup libusb_desc
* Get the USB device descriptor for a given device.
* 获得设备描述符
*
* This is a non-blocking function; the device descriptor is cached in memory.
* 参数:
* dev - 哪个设备
* desc - 输出参数, 用来保存设备描述符
*
* Note since libusb-1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, this
* function always succeeds.
*
* \param dev the device
* \param desc output location for the descriptor data
* \returns 0 on success or a LIBUSB_ERROR code on failure
* 返回值:
* 0 - 成功, 或其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev,
struct libusb_device_descriptor *desc);
```
**获得/释放配置描述符**
#### 2.7.2 获得/释放配置描述符
```c
/** \ingroup libusb_desc
* Get a USB configuration descriptor based on its index.
* This is a non-blocking function which does not involve any requests being
* sent to the device.
* 获得指定的配置描述符
*
* \param dev a device
* \param config_index the index of the configuration you wish to retrieve
* \param config output location for the USB configuration descriptor. Only
* valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
* after use.
* \returns 0 on success
* \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
* \returns another LIBUSB_ERROR code on error
* \see libusb_get_active_config_descriptor()
* \see libusb_get_config_descriptor_by_value()
* 参数:
* dev - 哪个设备
* config_index - 哪个配置
* config - 输出参数, 用来保存配置描述符, 使用完毕要调用libusb_free_config_descriptor()释放掉
*
* 返回值:
* 0 - 成功
* LIBUSB_ERROR_NOT_FOUND - 没有这个配置
* 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
uint8_t config_index, struct libusb_config_descriptor **config);
/** \ingroup libusb_desc
* Free a configuration descriptor obtained from
* libusb_get_active_config_descriptor() or libusb_get_config_descriptor().
* It is safe to call this function with a NULL config parameter, in which
* case the function simply returns.
*
* \param config the configuration descriptor to free
* 前面使用libusb_get_active_config_descriptor()libusb_get_config_descriptor()获得配置描述符,
* 用完后调用libusb_free_config_descriptor()释放掉
*/
void API_EXPORTED libusb_free_config_descriptor(
struct libusb_config_descriptor *config);
@@ -387,35 +369,30 @@ void API_EXPORTED libusb_free_config_descriptor(
```c
/** \ingroup libusb_syncio
* Perform a USB control transfer.
* 启动控制传输
*
* The direction of the transfer is inferred from the bmRequestType field of
* the setup packet.
* 传输方向在bmRequestType
* wValue,wIndex和wLength是host-endian字节序
*
* The wValue, wIndex and wLength fields values should be given in host-endian
* byte order.
*
* \param dev_handle a handle for the device to communicate with
* \param bmRequestType the request type field for the setup packet
* \param bRequest the request field for the setup packet
* \param wValue the value field for the setup packet
* \param wIndex the index field for the setup packet
* \param data a suitably-sized data buffer for either input or output
* (depending on direction bits within bmRequestType)
* \param wLength the length field for the setup packet. The data buffer should
* be at least this size.
* \param timeout timeout (in milliseconds) that this function should wait
* before giving up due to no response being received. For an unlimited
* timeout, use value 0.
* \returns on success, the number of bytes actually transferred
* \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out
* \returns LIBUSB_ERROR_PIPE if the control request was not supported by the
* device
* \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
* \returns LIBUSB_ERROR_BUSY if called from event handling context
* \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than
* 参数:
* dev_handle - 设备句柄
* bmRequestType - setup数据包的bmRequestType域
* bRequest - setup数据包的bRequest域
* wValue - setup数据包的wValue域
* wIndex - setup数据包的wIndex域
* data - 保存数据的buffer, 可以是in、out数据
* wLength - setup数据包的wLength域
* timeout - 超时时间(单位ms),就是这个函数能等待的最大时间; 0表示一直等待直到成功
*
* 返回值:
* 正整数 - 成功传输的数据的长度
* LIBUSB_ERROR_TIMEOUT - 超时
* LIBUSB_ERROR_PIPE - 设备不支持该请求
* LIBUSB_ERROR_NO_DEVICE - 设备未连接
* LIBUSB_ERROR_BUSY - 如果这个函数时在事件处理上下文(event handling context)里则返回这个错误
* LIBUSB_ERROR_INVALID_PARAM - 传输的字节超过OS或硬件的支持
* the operating system and/or hardware can support (see \ref asynclimits)
* \returns another LIBUSB_ERROR code on other failures
* 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle,
uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
@@ -428,49 +405,34 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle,
```c
/** \ingroup libusb_syncio
* Perform a USB bulk transfer. The direction of the transfer is inferred from
* the direction bits of the endpoint address.
* 启动批量传输
* 传输方向在endpoint的"方向位"里表示
*
* For bulk reads, the <tt>length</tt> field indicates the maximum length of
* data you are expecting to receive. If less data arrives than expected,
* this function will return that data, so be sure to check the
* <tt>transferred</tt> output parameter.
* 对于批量读参数length表示"期望读到的数据最大长度", 实际读到的长度保存在transferred参数里
*
* You should also check the <tt>transferred</tt> parameter for bulk writes.
* Not all of the data may have been written.
* 对于批量写, transferred参数表示实际发送出去的数据长度
*
* Also check <tt>transferred</tt> when dealing with a timeout error code.
* libusb may have to split your transfer into a number of chunks to satisfy
* underlying O/S requirements, meaning that the timeout may expire after
* the first few chunks have completed. libusb is careful not to lose any data
* that may have been transferred; do not assume that timeout conditions
* indicate a complete lack of I/O. See \ref asynctimeout for more details.
* 发生超时错误时也应该检查transferred参数。
* libusb会根据硬件的特点把数据拆分为一小段一小段地发送出去,
* 这意味着发送满某段数据后可能就发生超时错误需要根据transferred参数判断传输了多少数据。
*
* \param dev_handle a handle for the device to communicate with
* \param endpoint the address of a valid endpoint to communicate with
* \param data a suitably-sized data buffer for either input or output
* (depending on endpoint)
* \param length for bulk writes, the number of bytes from data to be sent. for
* bulk reads, the maximum number of bytes to receive into the data buffer.
* \param transferred output location for the number of bytes actually
* transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105),
* it is legal to pass a NULL pointer if you do not wish to receive this
* information.
* \param timeout timeout (in milliseconds) that this function should wait
* before giving up due to no response being received. For an unlimited
* timeout, use value 0.
* 参数:
* dev_handle - 设备句柄
* endpoint - 端点
* data - 保存数据的buffer, 可以是in、out数据
* length - 对于批量写,它表示要发送的数据长度; 对于批量读,它表示"要读的数据的最大长度"
* transferred - 输出参数,表示实际传输的数据长度
* timeout - 超时时间(单位ms),就是这个函数能等待的最大时间; 0表示一直等待直到成功
*
* \returns 0 on success (and populates <tt>transferred</tt>)
* \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates
* <tt>transferred</tt>)
* \returns LIBUSB_ERROR_PIPE if the endpoint halted
* \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see
* \ref libusb_packetoverflow
* \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
* \returns LIBUSB_ERROR_BUSY if called from event handling context
* \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than
* the operating system and/or hardware can support (see \ref asynclimits)
* \returns another LIBUSB_ERROR code on other failures
* 返回值:
* 0 - 成功根据transferred参数判断传输了多少长度的数据
* LIBUSB_ERROR_TIMEOUT - 超时, 根据transferred参数判断传输了多少长度的数据
* LIBUSB_ERROR_PIPE - 端点错误,端点被挂起了
* LIBUSB_ERROR_OVERFLOW - 溢出,设备提供的数据太多了
* LIBUSB_ERROR_NO_DEVICE - 设备未连接
* LIBUSB_ERROR_BUSY - 如果这个函数时在事件处理上下文(event handling context)里则返回这个错误
* LIBUSB_ERROR_INVALID_PARAM - 传输的字节超过OS或硬件的支持
* 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_bulk_transfer(libusb_device_handle *dev_handle,
unsigned char endpoint, unsigned char *data, int length,
@@ -483,50 +445,34 @@ int API_EXPORTED libusb_bulk_transfer(libusb_device_handle *dev_handle,
```c
/** \ingroup libusb_syncio
* Perform a USB interrupt transfer. The direction of the transfer is inferred
* from the direction bits of the endpoint address.
* 启动中断传输
* 传输方向在endpoint的"方向位"里表示
*
* For interrupt reads, the <tt>length</tt> field indicates the maximum length
* of data you are expecting to receive. If less data arrives than expected,
* this function will return that data, so be sure to check the
* <tt>transferred</tt> output parameter.
* 对于中断读参数length表示"期望读到的数据最大长度", 实际读到的长度保存在transferred参数里
*
* You should also check the <tt>transferred</tt> parameter for interrupt
* writes. Not all of the data may have been written.
* 对于中断写, transferred参数表示实际发送出去的数据长度不一定能发送完全部数据。
*
* Also check <tt>transferred</tt> when dealing with a timeout error code.
* libusb may have to split your transfer into a number of chunks to satisfy
* underlying O/S requirements, meaning that the timeout may expire after
* the first few chunks have completed. libusb is careful not to lose any data
* that may have been transferred; do not assume that timeout conditions
* indicate a complete lack of I/O. See \ref asynctimeout for more details.
* 发生超时错误时也应该检查transferred参数。
* libusb会根据硬件的特点把数据拆分为一小段一小段地发送出去,
* 这意味着发送满某段数据后可能就发生超时错误需要根据transferred参数判断传输了多少数据。
*
* The default endpoint bInterval value is used as the polling interval.
* 参数:
* dev_handle - 设备句柄
* endpoint - 端点
* data - 保存数据的buffer, 可以是in、out数据
* length - 对于批量写,它表示要发送的数据长度; 对于批量读,它表示"要读的数据的最大长度"
* transferred - 输出参数,表示实际传输的数据长度
* timeout - 超时时间(单位ms),就是这个函数能等待的最大时间; 0表示一直等待直到成功
*
* \param dev_handle a handle for the device to communicate with
* \param endpoint the address of a valid endpoint to communicate with
* \param data a suitably-sized data buffer for either input or output
* (depending on endpoint)
* \param length for bulk writes, the number of bytes from data to be sent. for
* bulk reads, the maximum number of bytes to receive into the data buffer.
* \param transferred output location for the number of bytes actually
* transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105),
* it is legal to pass a NULL pointer if you do not wish to receive this
* information.
* \param timeout timeout (in milliseconds) that this function should wait
* before giving up due to no response being received. For an unlimited
* timeout, use value 0.
*
* \returns 0 on success (and populates <tt>transferred</tt>)
* \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out
* \returns LIBUSB_ERROR_PIPE if the endpoint halted
* \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see
* \ref libusb_packetoverflow
* \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
* \returns LIBUSB_ERROR_BUSY if called from event handling context
* \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than
* the operating system and/or hardware can support (see \ref asynclimits)
* \returns another LIBUSB_ERROR code on other error
* 返回值:
* 0 - 成功根据transferred参数判断传输了多少长度的数据
* LIBUSB_ERROR_TIMEOUT - 超时, 根据transferred参数判断传输了多少长度的数据
* LIBUSB_ERROR_PIPE - 端点错误,端点被挂起了
* LIBUSB_ERROR_OVERFLOW - 溢出,设备提供的数据太多了
* LIBUSB_ERROR_NO_DEVICE - 设备未连接
* LIBUSB_ERROR_BUSY - 如果这个函数时在事件处理上下文(event handling context)里则返回这个错误
* LIBUSB_ERROR_INVALID_PARAM - 传输的字节超过OS或硬件的支持
* 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_interrupt_transfer(libusb_device_handle *dev_handle,
unsigned char endpoint, unsigned char *data, int length,
@@ -553,27 +499,28 @@ int API_EXPORTED libusb_interrupt_transfer(libusb_device_handle *dev_handle,
```c
/** \ingroup libusb_asyncio
* Allocate a libusb transfer with a specified number of isochronous packet
* descriptors. The returned transfer is pre-initialized for you. When the new
* transfer is no longer needed, it should be freed with
* libusb_free_transfer().
* 分配一个libusb_transfer结构体,
* 如果iso_packets不为0还会分配iso_packets个libusb_iso_packet_descriptor结构体
* 使用完毕后需要调用libusb_free_transfer()函数释放掉
*
* Transfers intended for non-isochronous endpoints (e.g. control, bulk,
* interrupt) should specify an iso_packets count of zero.
* 对于控制传输、批量传输、中断传输iso_packets参数需要设置为0
*
* For transfers intended for isochronous endpoints, specify an appropriate
* number of packet descriptors to be allocated as part of the transfer.
* The returned transfer is not specially initialized for isochronous I/O;
* you are still required to set the
* \ref libusb_transfer::num_iso_packets "num_iso_packets" and
* \ref libusb_transfer::type "type" fields accordingly.
* 对于实时传输需要指定iso_packets参数
* 这个函数会一起分配iso_packets个libusb_iso_packet_descriptor结构体。
* 这个函数返回的libusb_transfer结构体并未初始化
* 你还需要初始化它的这些成员:
* libusb_transfer::num_iso_packets
* libusb_transfer::type
*
* It is safe to allocate a transfer with some isochronous packets and then
* use it on a non-isochronous endpoint. If you do this, ensure that at time
* of submission, num_iso_packets is 0 and that type is set appropriately.
* 你可以指定iso_packets参数意图给实时传输分配结构体
* 但是你可以把这个结构题用于其他类型的传输,
* 在这种情况下只要确保num_iso_packets为0就可以。
*
* \param iso_packets number of isochronous packet descriptors to allocate. Must be non-negative.
* \returns a newly allocated transfer, or NULL on error
* 参数:
* iso_packets - 分配多少个isochronous packet descriptors to allocate
*
* 返回值:
* 返回一个libusb_transfer结构体或NULL
*/
DEFAULT_VISIBILITY
struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(
@@ -585,32 +532,31 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(
#### 2.9.3 填充控制传输
```c
* Helper function to populate the required \ref libusb_transfer fields
* for a control transfer.
/** \ingroup libusb_asyncio
* 构造控制传输结构体
*
* If you pass a transfer buffer to this function, the first 8 bytes will
* be interpreted as a control setup packet, and the wLength field will be
* used to automatically populate the \ref libusb_transfer::length "length"
* field of the transfer. Therefore the recommended approach is:
* -# Allocate a suitably sized data buffer (including space for control setup)
* -# Call libusb_fill_control_setup()
* -# If this is a host-to-device transfer with a data stage, put the data
* in place after the setup packet
* -# Call this function
* -# Call libusb_submit_transfer()
* 如果你传入buffer参数那么buffer的前面8字节会被当做"control setup packet"来解析,
* buffer的最后2字节表示wLength它也会被用来设置libusb_transfer::length
* 所以,建议使用流程如下:
* 1. 分配buffer这个buffer的前面8字节对应"control setup packet",后面的空间可以用来保存其他数据
* 2. 设置"control setup packet"通过调用libusb_fill_control_setup()函数来设置
* 3. 如果是要把数据发送个设备把要发送的数据放在buffer的后面(从buffer[8]开始放)
* 4. 调用libusb_fill_bulk_transfer
* 5. 提交传输: 调用libusb_submit_transfer()
*
* It is also legal to pass a NULL buffer to this function, in which case this
* function will not attempt to populate the length field. Remember that you
* must then populate the buffer and length fields later.
* 也可以让buffer参数为NULL
* 这种情况下libusb_transfer::length就不会被设置,
* 需要手工去设置ibusb_transfer::buffer、ibusb_transfer::length
*
* \param transfer the transfer to populate
* \param dev_handle handle of the device that will handle the transfer
* \param buffer data buffer. If provided, this function will interpret the
* first 8 bytes as a setup packet and infer the transfer length from that.
* This pointer must be aligned to at least 2 bytes boundary.
* \param callback callback function to be invoked on transfer completion
* \param user_data user data to pass to callback function
* \param timeout timeout for the transfer in milliseconds
* 参数:
* transfer - 要设置的libusb_transfer结构体
* dev_handle - 设备句柄
* buffer - 数据buffer如果不是NULL的话它前面8直接会被当做"control setup packet"来处理,
* 也会从buffer[6], buffer[7]把length提取出来用来设置libusb_transfer::length
* 这个buffer必须是2字节对齐
* callback - 传输完成时的回调函数
* user_data - 传给回调函数的参数
* timeout - 超时时间(单位: ms)
*/
static inline void libusb_fill_control_transfer(
struct libusb_transfer *transfer, libusb_device_handle *dev_handle,
@@ -624,17 +570,17 @@ static inline void libusb_fill_control_transfer(
```c
/** \ingroup libusb_asyncio
* Helper function to populate the required \ref libusb_transfer fields
* for a bulk transfer.
* 构造批量传输结构体
*
* \param transfer the transfer to populate
* \param dev_handle handle of the device that will handle the transfer
* \param endpoint address of the endpoint where this transfer will be sent
* \param buffer data buffer
* \param length length of data buffer
* \param callback callback function to be invoked on transfer completion
* \param user_data user data to pass to callback function
* \param timeout timeout for the transfer in milliseconds
* 参数:
* transfer - 要设置的libusb_transfer结构体
* dev_handle - 设备句柄
* endpoint - 端点
* buffer - 数据buffer
* length - buffer的数据长度
* callback - 传输完成时的回调函数
* user_data - 传给回调函数的参数
* timeout - 超时时间(单位: ms)
*/
static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer,
libusb_device_handle *dev_handle, unsigned char endpoint,
@@ -648,17 +594,17 @@ static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer,
```c
/** \ingroup libusb_asyncio
* Helper function to populate the required \ref libusb_transfer fields
* for an interrupt transfer.
* 构造中断传输结构体
*
* \param transfer the transfer to populate
* \param dev_handle handle of the device that will handle the transfer
* \param endpoint address of the endpoint where this transfer will be sent
* \param buffer data buffer
* \param length length of data buffer
* \param callback callback function to be invoked on transfer completion
* \param user_data user data to pass to callback function
* \param timeout timeout for the transfer in milliseconds
* 参数:
* transfer - 要设置的libusb_transfer结构体
* dev_handle - 设备句柄
* endpoint - 端点
* buffer - 数据buffer
* length - buffer的数据长度
* callback - 传输完成时的回调函数
* user_data - 传给回调函数的参数
* timeout - 超时时间(单位: ms)
*/
static inline void libusb_fill_interrupt_transfer(
struct libusb_transfer *transfer, libusb_device_handle *dev_handle,
@@ -672,18 +618,18 @@ static inline void libusb_fill_interrupt_transfer(
```c
/** \ingroup libusb_asyncio
* Helper function to populate the required \ref libusb_transfer fields
* for an isochronous transfer.
* 构造实时传输结构体
*
* \param transfer the transfer to populate
* \param dev_handle handle of the device that will handle the transfer
* \param endpoint address of the endpoint where this transfer will be sent
* \param buffer data buffer
* \param length length of data buffer
* \param num_iso_packets the number of isochronous packets
* \param callback callback function to be invoked on transfer completion
* \param user_data user data to pass to callback function
* \param timeout timeout for the transfer in milliseconds
* 参数:
* transfer - 要设置的libusb_transfer结构体
* dev_handle - 设备句柄
* endpoint - 端点
* buffer - 数据buffer
* length - buffer的数据长度
* num_iso_packets - 实时传输包的个数
* callback - 传输完成时的回调函数
* user_data - 传给回调函数的参数
* timeout - 超时时间(单位: ms)
*/
static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer,
libusb_device_handle *dev_handle, unsigned char endpoint,
@@ -697,18 +643,18 @@ static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer,
```c
/** \ingroup libusb_asyncio
* Submit a transfer. This function will fire off the USB transfer and then
* return immediately.
* 提交传输Submit,这个函数会启动传输,然后立刻返回
*
* \param transfer the transfer to submit
* \returns 0 on success
* \returns \ref LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
* \returns \ref LIBUSB_ERROR_BUSY if the transfer has already been submitted.
* \returns \ref LIBUSB_ERROR_NOT_SUPPORTED if the transfer flags are not supported
* by the operating system.
* \returns \ref LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than
* the operating system and/or hardware can support (see \ref asynclimits)
* \returns another LIBUSB_ERROR code on other failure
* 参数:
* transfer - 要传输的libusb_transfer结构体
*
* 返回值:
* 0 - 成功
* LIBUSB_ERROR_NO_DEVICE - 设备未连接
* LIBUSB_ERROR_BUSY - 这个传输已经提交过了
* LIBUSB_ERROR_NOT_SUPPORTED - 不支持这个传输
* LIBUSB_ERROR_INVALID_PARAM - 传输的字节超过OS或硬件的支持
* 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer);
```
@@ -717,41 +663,96 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer);
#### 2.9.8 处理事件
2个函数
4个函数其中2个没有`completed`后缀的函数过时了
```c
/** \ingroup libusb_poll
* Handle any pending events
* 处理任何"pengding的事件"
*
* Like libusb_handle_events_timeout_completed(), but without the completed
* parameter, calling this function is equivalent to calling
* libusb_handle_events_timeout_completed() with a NULL completed parameter.
* 使用异步传输函数时提交的tranfer结构体后就返回了。
* 可以使用本函数处理这些传输的返回结果。
*
* This function is kept primarily for backwards compatibility.
* All new code should call libusb_handle_events_completed() or
* libusb_handle_events_timeout_completed() to avoid race conditions.
* 如果timeval参数为0本函数会处理"当前、已经pending的事件",然后马上返回。
*
* \param ctx the context to operate on, or NULL for the default context
* \param tv the maximum time to block waiting for events, or an all zero
* timeval struct for non-blocking mode
* \returns 0 on success, or a LIBUSB_ERROR code on failure
* 如果timeval参数不为0并且当前没有待处理的事件本函数会阻塞以等待事件直到超时。
* 在等待过程中,如果事件发生了、或者得到了信号(signal),那么这个函数会提前返回。
*
* completed参数用来避免竞争如果它不为NULL:
* 本函数获得"event handling lock"后会判断completed指向的数值
* 如果这个数值非0(表示别的线程已经处理了、已经completed了)
* 则本函数会立刻返回(既然都completed了当然无需再处理)
*
* 参数:
* ctx - context(如果传入NULL则使用默认context)
* tv - 等待事件的最大时间0表示不等待
* completed - 指针可以传入NULL
*
* 返回值:
* 0 - 成功
* LIBUSB_ERROR_INVALID_PARAM - timeval参数无效
* 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_handle_events_timeout_completed(libusb_context *ctx,
struct timeval *tv, int *completed);
/** \ingroup libusb_poll
* 处理任何"pengding的事件"
*
* 跟libusb_handle_events_timeout_completed()类似,
* 就是调用"libusb_handle_events_timeout_completed(ctx, tv, NULL);"
* 最后的completed参数为NULL。
*
* 这个函数只是为了保持向后兼容新的代码建议使用libusb_handle_events_completed()或
* libusb_handle_events_timeout_completed()
* 这2个新函数可以处理竞争。
*
* 参数:
* ctx - context(如果传入NULL则使用默认context)
* tv - 等待事件的最大时间0表示不等待
*
* 返回值:
* 0 - 成功
* LIBUSB_ERROR_INVALID_PARAM - timeval参数无效
* 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_handle_events_timeout(libusb_context *ctx,
struct timeval *tv);
/** \ingroup libusb_poll
* Handle any pending events in blocking mode. There is currently a timeout
* hard-coded at 60 seconds but we plan to make it unlimited in future. For
* finer control over whether this function is blocking or non-blocking, or
* for control over the timeout, use libusb_handle_events_timeout_completed()
* instead.
* 处理任何"pengding的事件",以阻塞方式处理(blocking mode)
*
* This function is kept primarily for backwards compatibility.
* All new code should call libusb_handle_events_completed() or
* libusb_handle_events_timeout_completed() to avoid race conditions.
* 本函数的内部实现就是调用: libusb_handle_events_timeout_completed(ctx, &tv, completed);
* 超时时间设置为60秒
*
* \param ctx the context to operate on, or NULL for the default context
* \returns 0 on success, or a LIBUSB_ERROR code on failure
* 参数:
* ctx - context(如果传入NULL则使用默认context)
* completed - 指针可以传入NULL
*
* 返回值:
* 0 - 成功
* LIBUSB_ERROR_INVALID_PARAM - timeval参数无效
* 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_handle_events_completed(libusb_context *ctx,
int *completed);
/** \ingroup libusb_poll
* 处理任何"pengding的事件",以阻塞方式处理(blocking mode)
*
* 本函数的内部实现就是调用: libusb_handle_events_timeout_completed(ctx, &tv, NULL);
* 超时时间设置为60秒
*
* 这个函数只是为了保持向后兼容新的代码建议使用libusb_handle_events_completed()或
* libusb_handle_events_timeout_completed()
* 这2个新函数可以处理竞争。
*
* 参数:
* ctx - context(如果传入NULL则使用默认context)
*
* 返回值:
* 0 - 成功
* LIBUSB_ERROR_INVALID_PARAM - timeval参数无效
* 其他LIBUSB_ERROR错误码
*/
int API_EXPORTED libusb_handle_events(libusb_context *ctx);
```
@@ -764,31 +765,20 @@ int API_EXPORTED libusb_handle_events(libusb_context *ctx);
```c
/** \ingroup libusb_asyncio
* Free a transfer structure. This should be called for all transfers
* allocated with libusb_alloc_transfer().
* 释放libusb_transfer结构体
* 前面使用libusb_alloc_transfer()分配的结构体,要使用本函数来释放。
*
* If the \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_BUFFER
* "LIBUSB_TRANSFER_FREE_BUFFER" flag is set and the transfer buffer is
* non-NULL, this function will also free the transfer buffer using the
* standard system memory allocator (e.g. free()).
*
* It is legal to call this function with a NULL transfer. In this case,
* the function will simply return safely.
*
* It is not legal to free an active transfer (one which has been submitted
* and has not yet completed).
*
* \param transfer the transfer to free
* 如果libusb_transfer::flagsLIBUSB_TRANSFER_FREE_BUFFER位非0
* 那么会使用free()函数释放ibusb_transfer::buffer
*
* 不能使用本函数释放一个活动的传输结构体(active, 已经提交尚未结束)
*
*/
void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer);
```
## 3. 使用示例
在libusb源码的examples目录下有示例程序我们也有一些真实的案列。