您的位置:首页 > 汽车 > 时评 > 企业年金险是什么意思_重庆最新疫情最新消息_站长工具推荐_百度推广代理

企业年金险是什么意思_重庆最新疫情最新消息_站长工具推荐_百度推广代理

2025/4/16 22:31:57 来源:https://blog.csdn.net/XiaoXiaoPengBo/article/details/147082805  浏览:    关键词:企业年金险是什么意思_重庆最新疫情最新消息_站长工具推荐_百度推广代理
企业年金险是什么意思_重庆最新疫情最新消息_站长工具推荐_百度推广代理

 零.声明

本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下:

第一篇:蓝牙综合介绍 ,主要介绍蓝牙的一些概念,产生背景,发展轨迹,市面蓝牙介绍,以及蓝牙开发板介绍。

第二篇:Transport层介绍,主要介绍蓝牙协议栈跟蓝牙芯片之前的硬件传输协议,比如基于UART的H4,H5,BCSP,基于USB的H2等

第三篇:传统蓝牙controller介绍,主要介绍传统蓝牙芯片的介绍,包括射频层(RF),基带层(baseband),链路管理层(LMP)等

第四篇:传统蓝牙host介绍,主要介绍传统蓝牙的协议栈,比如HCI,L2CAP,SDP,RFCOMM,HFP,SPP,HID,AVDTP,AVCTP,A2DP,AVRCP,OBEX,PBAP,MAP等等一系列的协议吧。

第五篇:低功耗蓝牙controller介绍,主要介绍低功耗蓝牙芯片,包括物理层(PHY),链路层(LL)

第六篇:低功耗蓝牙host介绍,低功耗蓝牙协议栈的介绍,包括HCI,L2CAP,ATT,GATT,SM等

第七篇:蓝牙芯片介绍,主要介绍一些蓝牙芯片的初始化流程,基于HCI vendor command的扩展

第八篇:附录,主要介绍以上常用名词的介绍以及一些特殊流程的介绍等。

另外,开发板如下所示,对于想学习蓝牙协议栈的最好人手一套。以便更好的学习蓝牙协议栈,相信我,学完这一套视频你将拥有修改任何协议栈的能力(比如Linux下的bluez,Android下的bluedroid)。

-------------------------------------------------------------------------------------------------------------------------

蓝牙视频教程(跟韦东山老师合作):

https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22329603896.20.5aeb41f98e267j&id=693788592796

蓝牙交流扣扣群:765961169

Github代码:GitHub - sj15712795029/bluetooth_stack: 这是一个开源的双模蓝牙协议栈(bluetooth.stack)(btstack),可以运行在STM32,Linux.,包含HCI,L2CAP,SDP,RFCOMM,HFP,SPP,A2DP,AVRCP,AVDTP,AVCTP,OBEX,PBAP等协议,后续会继续维护,以达到商用的目的

入手开发板:https://shop220811498.taobao.com/category-1542116976.htm?spm=a1z10.5-c-s.w4010-22329603913.7.39ca7dbe2EA0K3&search=y&catName=%C0%B6%D1%C0%BF%AA%B7%A2%B0%E5#bd

蓝牙学习目录一篇文章足够你学习蓝牙技术,提供史上最全的蓝牙技术(传统蓝牙/低功耗蓝牙)文章总结,文档下载总结(2020/12/11更新)_Wireless_Link的博客-CSDN博客_蓝牙eir

--------------------------------------------------------------------------------------------------------------------------

本文的目的就是在ubuntu上驱动CSR8510,大概有两种做法:

  • 原生的linux默认免驱方式
  • 使用驱动方式(USB转tty) + 蓝牙协议栈方式来驱动
  • 使用libusb + 蓝牙协议栈方式来驱动

其中免驱方式我们已经在剖析Linux蓝牙子系统来驱动USB接口的蓝牙(CSR8510蓝牙dongle)原理-CSDN博客介绍过了,所以不再赘述,我们本文的目的是最后一种用libusb来驱动

一. CSR8510介绍

CSR8510 是 Qualcomm(高通)旗下CSR公司推出的一款 蓝牙无线通信芯片,主要应用于蓝牙适配器(USB Dongle)或嵌入式设备中,支持蓝牙数据传输和音频传输功能。以下是其关键信息:


1. 主要特性

  • 蓝牙版本:支持 蓝牙4.0(兼容蓝牙2.1+EDR、3.0、4.0 BLE),支持双模(经典蓝牙 + 低功耗蓝牙 BLE)。
  • 接口:集成 USB 2.0 控制器,可直接通过USB接口与主机设备(如PC、智能设备)连接。
  • 协议支持
    • 经典蓝牙协议:HID(键鼠)、A2DP(音频传输)、HFP(通话)、AVRCP(遥控)、SPP(串口)等。
    • 低功耗蓝牙(BLE):适用于物联网设备、传感器等低功耗场景。
  • 传输速率:理论最大速率 3 Mbps(EDR增强速率)。
  • 传输距离:约 10米(视环境干扰情况而定)。

2. 典型应用场景

  • 蓝牙适配器:用于为无蓝牙功能的电脑、电视等设备添加蓝牙连接能力。
  • 无线音频设备:连接蓝牙耳机、音箱,支持A2DP高品质音频传输。
  • 外设连接:无线键鼠、游戏手柄、打印机等(通过HID/SPP协议)。
  • 物联网(IoT):通过BLE与传感器、智能家居设备通信。

3. 技术优势

  • 低功耗:BLE模式显著降低能耗,适合电池供电设备。
  • 兼容性:广泛支持Windows、Linux、macOS等操作系统。
  • 集成度高:单芯片集成射频、基带和协议栈,简化设计。

4. 注意事项

  • 驱动依赖:在部分系统中(如Windows 10/11)可能需手动安装驱动。
  • 版本差异:不同厂商的CSR8510适配器可能阉割部分功能(如仅支持经典蓝牙,未启用BLE)。
  • 性能限制:蓝牙4.0的传输速率和延迟不如更新的蓝牙5.x,若需更高性能需选择新款芯片。

二. 卸载原生的驱动

目前有两种方式来禁用掉跟libusb的冲突

1. 卸载驱动方式

在Ubuntu系统中,CSR8510蓝牙适配器的驱动通常由内核模块(如 btusb)提供,属于系统默认集成的一部分。所以如果要做后两种方式,需要先把原生的免驱方式彻底屏蔽掉,也就是不让系统自动加载btusb驱动

a. 确认驱动信息

首先,确认系统是否已识别设备及当前加载的驱动:

lsmod | grep -i btusb

若输出显示 btusb 模块,则表明系统正使用该驱动。

b. 尝试临时卸载驱动

可临时移除 btusb 模块(需root权限):

sudo modprobe -r btusb

卸载后我们再查看btusb驱动已经不存在了

在这里我们就不用永久方式卸载btusb驱动了哈,风险比较大,有的小伙伴可能恢复不过来,所以我就不介绍了,但是只能告诉你们是可行的哈

2. libusb函数禁用到驱动

我们就直接上代码了哈,不用做更多的解释

if (libusb_kernel_driver_active(vnd_usb.dev_handle, 0) == 1) {result = libusb_detach_kernel_driver(vnd_usb.dev_handle, 0);if (result != 0) {ALOGE("libusb_detach_kernel_driver fail: %s", libusb_error_name(result));libusb_close(vnd_usb.dev_handle);libusb_exit(vnd_usb.usb_context);return;}
}

三. USB蓝牙的概念

Core spec定义如下

可以看到

hci command是用Control类型来控制,interface endpoint是0

hci event是用Interrupt类型来接收,interface endpoint是0x81

hci acl是用Bulk类型来收发数据,interface endpoint是0x82(IN),0x02(OUT)

hci sco是用isoch类型来收发数据,interface endpoint是0x83(IN),0x03(OUT)

HCI 数据类型

包类型标识

传输方向

USB 端点

libusb 函数

Command

0x01

Host→Dev

EP2 OUT (0x02)

libusb_control_transfer

Event

0x04

Dev→Host

EP1 IN (0x81)

libusb_interrupt_transfer

ACL Data

0x02

双向

EP2 OUT (0x02)/IN (0x82)

libusb_bulk_transfer

SCO Data

0x03

双向

(需确认是否支持)

libusb_isochronous_transfer

NOTED:需要注意的是H4跟H2出了uart跟usb的差异外,h2没有h4 transport的packet type哈,为啥呢?因为每种type都有EP地址,所以不需要,这个很好理解!

四. 使用libusb驱动

libusb是一个开源的、跨平台的用户态 USB 设备驱动库(USB host角色),允许开发者在不依赖操作系统内核驱动的情况下直接与 USB 设备通信。它广泛应用于嵌入式系统、逆向工程、数据采集、自定义设备控制等领域。

  • 跨平台支持
    • Linux / macOS / Windows / Android 等。
    • 统一 API,无需为不同平台编写不同代码。
  • 用户态驱动
    • 无需编写内核驱动,直接通过用户态程序操作 USB 设备。
    • 开发效率高,调试方便。
  • 异步 & 同步传输
    • 支持同步阻塞式操作(如 libusb_bulk_transfer)。
    • 提供异步非阻塞接口(如 libusb_submit_transfer),适合高性能场景。
  • 设备枚举与管理
    • 支持 USB 设备发现、打开、关闭、配置接口等。
    • 获取设备描述符(厂商 ID、产品 ID、序列号等)。
  • 传输模式
    • 控制传输(Control Transfer):用于设备配置(如 libusb_control_transfer)。
    • 批量传输(Bulk Transfer):大数据量传输(如文件读写)。
    • 中断传输(Interrupt Transfer):实时性要求高的场景(如 HID 设备)。
    • 等时传输(Isochronous Transfer):音视频流传输(需硬件支持)。

我们就是用libusb来驱动CSR8510

整个架构包含以下组件:

  • 蓝牙协议栈:这个不用做过多解释哈·
  • libusb:这个充当usb host角色,直接用libusb来操作usb设备,不需要内核介入
  • CSR8510:蓝牙dongle

下面我们就来说明下来驱动csr8510的步骤吧

1. libusb的初始化

libusb_context *usb_context;result = libusb_init(&vnd_usb.usb_context);
if (result < 0) {ALOGE("usb_vendor_open fail: %s", libusb_error_name(result));return;
}

libusb_initlibusb 库的初始化函数,用于创建并初始化 libusb 的上下文(Context)。它是所有 libusb 操作的起点,必须在调用其他 libusb 函数前执行。以下是详细解释:

函数原型

int libusb_init(libusb_context **ctx);

参数

  • ctx:指向 libusb_context 指针的指针。如果传入 NULL,libusb 会使用默认的全局上下文;如果传入非 NULL 的指针地址,则会创建独立的上下文(适用于多线程或复杂场景)。

返回值

  • LIBUSB_SUCCESS (0):初始化成功。
  • 负数:错误码(如内存不足、权限问题等)。

2. libusb匹配特定的usb设备(csr8510)

libusb_device_handle *dev_handle;vnd_usb.dev_handle = libusb_open_device_with_vid_pid(vnd_usb.usb_context, CSR8510_USB_VID, CSR8510_USB_PID);
if (!vnd_usb.dev_handle) {ALOGE("usb_vendor_open can not find 0x%04x:0x%04x device",CSR8510_USB_VID,CSR8510_USB_PID);libusb_exit(vnd_usb.usb_context);return;
}

libusb_open_device_with_vid_pidlibusb 库中的一个便捷函数,用于通过 厂商ID(VID)产品ID(PID) 快速打开匹配的 USB 设备。它简化了设备发现和初始化的流程,适用于已知目标设备 VID/PID 的场景。

函数原型

libusb_device_handle* libusb_open_device_with_vid_pid(libusb_context* ctx,      // libusb 上下文(通常填 NULL)uint16_t vendor_id,       // 设备厂商ID(VID)uint16_t product_id       // 设备产品ID(PID)
);

参数

  • ctx:libusb 上下文指针。传入 NULL 表示使用默认全局上下文。
  • vendor_id:目标设备的 16 位厂商 ID(VID),例如 0x1234
  • product_id:目标设备的 16 位产品 ID(PID),例如 0x5678

返回值

  • 成功:返回已打开的 USB 设备句柄(libusb_device_handle*)。
  • 失败:返回 NULL(设备未找到或打开失败)。

其中csr8510的vid/pid定义如下:

#define CSR8510_USB_VID 0x0a12
#define CSR8510_USB_PID 0x0001

我们是通过lsusb来查看的哈

3. libusb卸载内核驱动

if (libusb_kernel_driver_active(vnd_usb.dev_handle, 0) == 1) {result = libusb_detach_kernel_driver(vnd_usb.dev_handle, 0);if (result != 0) {ALOGE("libusb_detach_kernel_driver fail: %s", libusb_error_name(result));libusb_close(vnd_usb.dev_handle);libusb_exit(vnd_usb.usb_context);return;}
}

a. libusb_kernel_driver_active

功能

  • 检测内核驱动是否绑定了设备的某个接口
  • 当操作系统内核已为 USB 设备的某个接口加载了驱动(例如 USB 串口驱动、HID 驱动等),用户态程序需要通过此函数确认驱动状态。

原型

int libusb_kernel_driver_active(libusb_device_handle *dev_handle, int interface_number);

参数

  • dev_handle:已打开的 USB 设备句柄。
  • interface_number:要检查的接口编号(通常为 0, 1, 2...)。

返回值

  • 1:内核驱动已绑定该接口。
  • 0:内核驱动未绑定。
  • 负数:错误码(如 LIBUSB_ERROR_NO_DEVICE 表示设备已断开)。

b. libusb_detach_kernel_driver

功能

  • 解除内核驱动对 USB 设备接口的绑定
  • 用户态程序需要通过此函数释放内核驱动对接口的控制权,才能通过 libusb 直接操作设备。

原型

int libusb_detach_kernel_driver(libusb_device_handle *dev_handle, int interface_number);

参数

  • dev_handle:已打开的 USB 设备句柄。
  • interface_number:要解除绑定的接口编号。

返回值

  • 0:成功解除绑定。
  • 负数:错误码(如 LIBUSB_ERROR_NOT_FOUND 表示驱动未绑定)。

4. libusb发现usb interface/声明

其中发现usb interface是可选的操作,正常你如果想做成一个通用的,鉴于不同的芯片USB EP addr可能有细微差异,所以正常应该需要扫描USB EP addr,但是我们csr8510是固定的,所以我们就不做这个工作了,但是声明还是要做的,我们来看下代码

result = libusb_claim_interface(vnd_usb.dev_handle, 0);if (result < 0) {ALOGE("libusb_claim_interface: %s", libusb_error_name(result));libusb_close(vnd_usb.dev_handle);libusb_exit(vnd_usb.usb_context);return;}

我们来介绍下libusb_claim_interface函数

功能

  • 声明对 USB 设备某个接口的独占访问权
  • 在操作 USB 设备前,必须通过此函数声明要使用的接口(Interface),否则无法进行数据传输。

原型

int libusb_claim_interface(libusb_device_handle *dev_handle, int interface_number);

参数

  • dev_handle:已打开的 USB 设备句柄。
  • interface_number:接口编号(通常为 0, 1, 2...,根据设备描述符确定)。

返回值

  • 0:成功声明接口。
  • 负数:错误码(如 LIBUSB_ERROR_BUSY 表示接口已被占用)。

关键作用

  • 解除内核驱动占用(Linux 特有):
    在调用前需确保内核驱动已解除绑定(通过 libusb_detach_kernel_driver)。
  • 独占访问
    同一时刻只能有一个程序(或线程)操作该接口。
  • 资源管理
    必须与 libusb_release_interface 配对使用。

5. libusb发送hci command/acl数据

a. 发送hci command

void send_hci_command_packet(uint8_t *data, int32_t len) 
{int retry_count = 0;int result = 0;const char* func_name = __func__;do {result = libusb_control_transfer(vnd_usb.dev_handle,LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,0x00, 0x0000, 0x0000, data, len, 1000);if (result >= 0) {if (result == len) {return;}ALOGW("%s: Partial transfer: sent %d/%d bytes (retry %d/%d)", func_name, result, len, retry_count+1, MAX_RETRY_ATTEMPTS);result = LIBUSB_ERROR_IO;} else {ALOGW("%s: Attempt %d/%d failed: %s (%d)", func_name, retry_count+1, MAX_RETRY_ATTEMPTS,libusb_error_name(result), result);}if (result == LIBUSB_ERROR_NO_DEVICE || result == LIBUSB_ERROR_NOT_FOUND ||result == LIBUSB_ERROR_ACCESS) {break;}if (retry_count < MAX_RETRY_ATTEMPTS) {usleep(RETRY_DELAY_MS * 1000);}} while (retry_count++ < MAX_RETRY_ATTEMPTS);ALOGE("%s: Failed after %d attempts: %s (%d), last sent %d/%d bytes",func_name, retry_count, libusb_error_name(result), result, (result > 0) ? result : 0, len);
}

我们发送hci comamnd主要通过libusb_control_transfer函数,下面我们来介绍下这个函数的功能

功能

  • 执行 USB 控制传输(Control Transfer)
  • 控制传输用于设备配置、命令发送、状态查询等,是 USB 协议中的基础传输类型。

原型

int libusb_control_transfer(libusb_device_handle *dev_handle,uint8_t bmRequestType,  // 请求类型(方向/类型/接收方)uint8_t bRequest,        // 请求码(如 GET_DESCRIPTOR)uint16_t wValue,         // 请求参数(根据请求码定义)uint16_t wIndex,         // 接口/端点索引(根据请求码定义)unsigned char *data,     // 数据缓冲区uint16_t wLength,        // 数据长度unsigned int timeout     // 超时时间(毫秒)
);

返回值

  • 成功:实际传输的字节数。
  • 失败:负数错误码(如 LIBUSB_ERROR_TIMEOUT)。

典型用途

  • 获取设备描述符(如 GET_DESCRIPTOR 请求)。
  • 设置设备配置(如 SET_CONFIGURATION)。
  • 发送厂商自定义命令(Vendor-Specific Commands)。

b. 发送hci acl

void send_hci_acl_packet(uint8_t *data, int32_t len) 
{int retry_count = 0;int32_t transferred = 0;int result = 0;const char* func_name = __func__;do {result = libusb_bulk_transfer(vnd_usb.dev_handle, BT_USB_ACL_OUT_EP_ADDR, data, len, &transferred, 1000);if (result == LIBUSB_SUCCESS) {if (transferred == len) {return;}ALOGW("%s: Partial transfer: sent %d/%d bytes (retry %d/%d)", func_name, transferred, len, retry_count+1, MAX_RETRY_ATTEMPTS);result = LIBUSB_ERROR_IO;} else {ALOGW("%s: Attempt %d/%d failed: %s (%d)", func_name, retry_count+1, MAX_RETRY_ATTEMPTS,libusb_error_name(result), result);}switch (result) {case LIBUSB_ERROR_PIPE:libusb_clear_halt(vnd_usb.dev_handle, BT_USB_ACL_OUT_EP_ADDR);break;case LIBUSB_ERROR_NO_DEVICE:case LIBUSB_ERROR_NOT_FOUND:goto final_error;}if (retry_count < MAX_RETRY_ATTEMPTS) {usleep(RETRY_DELAY_MS * 1000);}} while (retry_count++ < MAX_RETRY_ATTEMPTS);final_error:ALOGE("%s: Failed after %d attempts: %s (%d), last sent %d/%d bytes",func_name, retry_count, libusb_error_name(result), result, transferred, len);
}

我们发送hci acl数据主要通过libusb_bulk_transfer这个函数,下面我们来介绍下这个函数的功能

功能

  • 执行 USB 批量传输(Bulk Transfer)
  • 批量传输用于可靠的大数据量传输(如文件读写),无实时性要求但保证数据完整性。

原型

int libusb_bulk_transfer(libusb_device_handle *dev_handle,unsigned char endpoint,  // 端点地址(含方向,如 0x81 表示 IN 端点)unsigned char *data,     // 数据缓冲区int length,              // 数据长度int *transferred,        // 实际传输的字节数(输出参数)unsigned int timeout     // 超时时间(毫秒)
);

返回值

  • 0:传输成功。
  • 负数:错误码(如 LIBUSB_ERROR_PIPE 表示端点错误)。

关键特性

  • 方向标识
    端点地址的最高位表示方向(0x80 表示 IN,0x00 表示 OUT)。
  • 可靠性
    数据传输保证完整性,出错时会重试。
  • 大块数据
    适合传输文件、固件等大数据块。

6. libusb接收hci event/acl数据

libusb有同步跟异步接收数据的方式,同步方式比较简单,就是while loop一直读取event跟acl数据就可以了,但是这种方式对于实时性无法得到保证,对于播放音乐的场景就比较局限,所以我们直接采取异步方式了,我们先来看下event跟acl的EP

所以我们直接贴代码

typedef struct {struct libusb_transfer* event_transfer;struct libusb_transfer* acl_transfer;bool async_transfer_running;pthread_mutex_t lock;
} async_usb_ctx_t;static void async_transfer_cb(struct libusb_transfer* transfer)
{int result;async_usb_ctx_t* ctx = (async_usb_ctx_t*)transfer->user_data;if (transfer->status == LIBUSB_TRANSFER_STALL){ALOGE("Transfer stalled, trying again");result = libusb_clear_halt(vnd_usb.dev_handle, transfer->endpoint);if (result) {ALOGE("libusb_clear_halt fail: %s", libusb_error_name(result));}result = libusb_submit_transfer(transfer);if (result) {ALOGE("re-submitting transfer fail: %s", libusb_error_name(result));}}if(transfer->status == LIBUSB_TRANSFER_COMPLETED){if(transfer->endpoint == BT_USB_EVENT_EP_ADDR){uint8_t pkt_with_type[transfer->actual_length + 1];pkt_with_type[0] = HCI_EVENT_PKT;memcpy(pkt_with_type + 1, transfer->buffer, transfer->actual_length);write(((osi_serial_i_t*)vnd_usb.vendor_fd)->fd, pkt_with_type, transfer->actual_length + 1);}else if(transfer->endpoint == BT_USB_ACL_IN_EP_ADDR){uint8_t pkt_with_type[transfer->actual_length + 1];pkt_with_type[0] = HCI_ACLDATA_PKT;memcpy(pkt_with_type + 1, transfer->buffer, transfer->actual_length);write(((osi_serial_i_t*)vnd_usb.vendor_fd)->fd,pkt_with_type,transfer->actual_length + 1);}}pthread_mutex_lock(&ctx->lock);if (ctx->async_transfer_running) {libusb_submit_transfer(transfer);}pthread_mutex_unlock(&ctx->lock);}async_usb_ctx_t* async_usb_init(libusb_device_handle* dev_handle) {async_usb_ctx_t* ctx = calloc(1, sizeof(async_usb_ctx_t));if (!ctx) return NULL;ctx->event_transfer = libusb_alloc_transfer(0);if (!ctx->event_transfer) goto error;ctx->acl_transfer = libusb_alloc_transfer(0);if (!ctx->acl_transfer) goto error;libusb_fill_interrupt_transfer(ctx->event_transfer,dev_handle,BT_USB_EVENT_EP_ADDR,data_recv,sizeof(data_recv),async_transfer_cb,ctx,100);libusb_fill_bulk_transfer(ctx->acl_transfer,dev_handle,BT_USB_ACL_IN_EP_ADDR,data_recv,sizeof(data_recv),async_transfer_cb,ctx,100);pthread_mutex_init(&ctx->lock, NULL);return ctx;error:if (ctx->event_transfer) libusb_free_transfer(ctx->event_transfer);if (ctx->acl_transfer) libusb_free_transfer(ctx->acl_transfer);free(ctx);return NULL;
}void async_usb_start(async_usb_ctx_t* ctx) {pthread_mutex_lock(&ctx->lock);ctx->async_transfer_running = true;int result = libusb_submit_transfer(ctx->event_transfer);if (result != LIBUSB_SUCCESS) {ALOGE("libusb_submit_transfer fail: %s", libusb_error_name(result));}result = libusb_submit_transfer(ctx->acl_transfer);if (result != LIBUSB_SUCCESS) {ALOGE("libusb_submit_transfer fail: %s", libusb_error_name(result));}pthread_mutex_unlock(&ctx->lock);
}void async_usb_stop(async_usb_ctx_t* ctx) {pthread_mutex_lock(&ctx->lock);ctx->async_transfer_running = false;if (ctx->event_transfer) {libusb_cancel_transfer(ctx->event_transfer);}if (ctx->acl_transfer) {libusb_cancel_transfer(ctx->acl_transfer);}pthread_mutex_unlock(&ctx->lock);
}void async_usb_cleanup(async_usb_ctx_t* ctx) {async_usb_stop(ctx);libusb_free_transfer(ctx->event_transfer);libusb_free_transfer(ctx->acl_transfer);pthread_mutex_destroy(&ctx->lock);free(ctx);
}

然后在接收线程中使用while loop来监听

while (vnd_usb.u2s_thread_runing) {struct timeval tv = {0, 100000}; // 100mslibusb_handle_events_timeout_completed(NULL, &tv, NULL);}

我们来解释下其中用到的各个API

a. libusb_alloc_transfer

功能

  • 分配并初始化一个异步传输结构体libusb_transfer)。
  • 用于准备异步传输(如批量、中断、控制或等时传输)所需的内存资源。

原型

struct libusb_transfer* libusb_alloc_transfer(int iso_packets);

参数

  • iso_packets:等时传输(Isochronous Transfer)的包数量,非等时传输填 0

返回值

  • 成功:指向 libusb_transfer 结构体的指针。
  • 失败:NULL(内存不足)。

b. libusb_fill_interrupt_transfer

功能

  • 填充中断传输(Interrupt Transfer)参数libusb_transfer 结构体。
  • 用于配置中断端点的异步传输。

原型

void libusb_fill_interrupt_transfer(struct libusb_transfer *transfer,  // 已分配的传输结构体libusb_device_handle *dev_handle,  // 设备句柄unsigned char endpoint,            // 端点地址(含方向)unsigned char *buffer,             // 数据缓冲区int length,                        // 缓冲区长度libusb_transfer_cb_fn callback,    // 传输完成回调函数void *user_data,                   // 用户自定义数据(传递给回调)unsigned int timeout               // 超时时间(毫秒)
);

c. libusb_fill_bulk_transfer

功能

  • 填充批量传输(Bulk Transfer)参数libusb_transfer 结构体。
  • 用于配置批量端点的异步传输。

原型

void libusb_fill_bulk_transfer(struct libusb_transfer *transfer,libusb_device_handle *dev_handle,unsigned char endpoint,unsigned char *buffer,int length,libusb_transfer_cb_fn callback,void *user_data,unsigned int timeout
);

d. libusb_submit_transfer

功能

  • 提交异步传输请求到 libusb 事件系统。
  • 传输将在后台执行,完成后触发回调函数。

原型

int libusb_submit_transfer(struct libusb_transfer *transfer);

返回值

  • 0:提交成功。
  • 负数:错误码(如 LIBUSB_ERROR_NO_DEVICE 设备已断开)。

e. libusb_cancel_transfer

功能

  • 取消已提交但未完成的传输
  • 若传输正在进行中,会尝试终止传输并触发回调函数。

原型

int libusb_cancel_transfer(struct libusb_transfer *transfer);

返回值

  • 0:取消请求已提交(不保证传输立即停止)。
  • 负数:传输已完成或已取消。

f. libusb_free_transfer

功能

  • 释放由 libusb_alloc_transfer 分配的传输结构体
  • 必须在传输完成或取消后调用,否则会导致内存泄漏。

原型

void libusb_free_transfer(struct libusb_transfer *transfer);

g. 关键注意事项

生命周期管理

    • 传输结构体必须在回调中或明确取消后释放。
    • 缓冲区内存需在传输期间保持有效。

线程安全

    • 异步操作依赖事件循环线程,需确保 libusb_handle_events/libusb_handle_events_timeout_completed 在独立线程运行。
    • 回调函数中避免阻塞操作。

错误处理

    • 在回调中检查 transfer->status
    • 处理 LIBUSB_TRANSFER_CANCELLEDLIBUSB_TRANSFER_ERROR 状态。

性能优化

    • 批量传输适合大数据量,中断传输适合小数据实时传输。
    • 使用多个并发的传输结构体提高吞吐量。

h. 函数对比总结

函数

作用

调用时机

libusb_alloc_transfer

分配传输结构体

传输开始前

libusb_fill_*_transfer

配置传输参数

提交传输前

libusb_submit_transfer

提交异步请求

参数配置完成后

libusb_cancel_transfer

取消进行中的传输

需要提前终止传输时

libusb_free_transfer

释放传输结构体

传输完成或取消后

掌握这些 API 可实现高性能、非阻塞的 USB 通信,适用于实时数据采集或低延迟控制场景。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com