diff --git a/IMX6ULL/doc_pic/12_USB/06_libusb的使用.md b/IMX6ULL/doc_pic/12_USB/06_libusb的使用.md
index 0c26573..52f1bcb 100644
--- a/IMX6ULL/doc_pic/12_USB/06_libusb的使用.md
+++ b/IMX6ULL/doc_pic/12_USB/06_libusb的使用.md
@@ -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.
+ * 返回一个list,list里含有当前系统中所有的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
- * idVendor/idProduct 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 dev, 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 bInterfaceNumber 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 dev, the kernel
- * driver will be re-attached after releasing the interface.
- *
- * \param dev_handle a device handle
- * \param interface_number the bInterfaceNumber 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 length 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
- * transferred output parameter.
+ * 对于批量读,参数length表示"期望读到的数据最大长度", 实际读到的长度保存在transferred参数里
*
- * You should also check the transferred parameter for bulk writes.
- * Not all of the data may have been written.
+ * 对于批量写, transferred参数表示实际发送出去的数据长度
*
- * Also check transferred 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 transferred)
- * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates
- * transferred)
- * \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 length 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
- * transferred output parameter.
+ * 对于中断读,参数length表示"期望读到的数据最大长度", 实际读到的长度保存在transferred参数里
*
- * You should also check the transferred parameter for interrupt
- * writes. Not all of the data may have been written.
+ * 对于中断写, transferred参数表示实际发送出去的数据长度,不一定能发送完全部数据。
*
- * Also check transferred 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 transferred)
- * \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::flags的LIBUSB_TRANSFER_FREE_BUFFER位非0,
+ * 那么会使用free()函数释放ibusb_transfer::buffer
+ *
+ * 不能使用本函数释放一个活动的传输结构体(active, 已经提交尚未结束)
+ *
*/
void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer);
```
-
-
-
-
## 3. 使用示例
在libusb源码的examples目录下有示例程序,我们也有一些真实的案列。