1.版本:LIBUSB 1.x
2.HID的数据传输方式,通常是中断模式。
3.bEndpointAddress : 0x81 (Direction=IN EndpointID=1)
这个属性才是读取的节点。usb->pc
4.bEndpointAddress : 0x02 (Direction=OUT EndpointID=2)
pc->usb
5. bInterval 查询频率,ms,
必须手动创建查询线程 才能实现异步读取操作
6.热插拔回调
USB摇杆访问成功!
找到USB设备 !
端口号: 6e
总线号: 1
bDescriptorType: 4
bEndpointAddress: 02h
传输类型: 03h
wMaxPacketSize: 64
传输速率: 10 ms
static libusb_device_handle* g_usb_handle;
static libusb_context *ctx;
static libusb_interface_descriptor *describe;
static libusb_transfer *main_transfer;
/// 热插拔回调事件
void hotplugin(){
while (1) {
libusb_handle_events_completed(ctx, NULL);
std::this_thread::sleep_for( std::chrono::milliseconds(1000) ) ;
}
}
static int LIBUSB_CALL
usb_arrived_callback(struct libusb_context *_ctx, struct libusb_device *dev,
libusb_hotplug_event event, void *userdata)
{
struct libusb_device_handle *handle;
struct libusb_device_descriptor desc;
unsigned char buf[512];
int rc;
libusb_get_device_descriptor(dev, &desc);
// printf("Add usb device: \n");
// printf("\tCLASS(0x%x) SUBCLASS(0x%x) PROTOCOL(0x%x)\n",desc.bDeviceClass, desc.bDeviceSubClass, desc.bDeviceProtocol);
// printf("\tVENDOR(0x%x) PRODUCT(0x%x)\n", desc.idVendor, desc.idProduct);
if((desc.idVendor == user_device.idVendor) && (desc.idProduct == user_device.idProduct)){
g_usb_handle = libusb_open_device_with_vid_pid(NULL, user_device.idVendor, user_device.idProduct);
int ret = 0;
struct libusb_config_descriptor *config;
ret = libusb_get_config_descriptor(dev, 0, &config);
if (LIBUSB_SUCCESS != ret) {
printf("不能获取设备描述符\n");
}
user_device.outEndPoint = (config->interface->altsetting->endpoint->bEndpointAddress & 0x07);
describe = const_cast<libusb_interface_descriptor*>(config->interface->altsetting);
printf(" 端口号: %0x\n", libusb_get_device_address(dev));
printf(" 总线号: %0x\n", libusb_get_bus_number(dev));
printf(" bDescriptorType: %d\n", config->interface->altsetting->bDescriptorType);
printf(" bEndpointAddress: %02xh\n", config->interface->altsetting->endpoint->bEndpointAddress);
printf(" 传输类型: %02xh\n", config->interface->altsetting->endpoint->bmAttributes);
printf(" wMaxPacketSize: %d\n", config->interface->altsetting->endpoint->wMaxPacketSize);
printf(" 传输速率: %d ms\n", config->interface->altsetting->endpoint->bInterval);
user_device.ms_Request = config->interface->altsetting->endpoint->bInterval;
//libusb_free_config_descriptor(config);
if(g_usb_handle == NULL) {
qWarning("拒绝访问USB设备!\n");
qWarning("请USB检查驱动,权限!\n");
user_device.isOpen= false;
return -1;
}else {
user_device.isOpen= true;
qDebug()<<"USB摇杆访问成功!";
}
}else {
return 0;
rc = libusb_open(dev, &handle);
if (LIBUSB_SUCCESS != rc) {
printf("Could not open USB device\n");
return 0;
}
memset(buf, 0, sizeof(buf));
rc = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, buf, sizeof(buf));
if (rc < 0) {
printf("Get Manufacturer failed\n");
} else {
printf("\tManufacturer: %s\n", buf);
}
memset(buf, 0, sizeof(buf));
rc = libusb_get_string_descriptor_ascii(handle, desc.iProduct, buf, sizeof(buf));
if (rc < 0) {
printf("Get Product failed\n");
} else {
printf("\tProduct: %s\n", buf);
}
memset(buf, 0, sizeof(buf));
rc = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, buf, sizeof(buf));
if (rc < 0) {
printf("Get SerialNumber failed\n");
} else {
printf("\tSerialNumber: %s\n", buf);
}
libusb_close(handle);
}
return 0;
}
static int LIBUSB_CALL
usb_left_callback(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event, void *userdata)
{
struct libusb_device_descriptor desc;
libusb_get_device_descriptor(dev, &desc);
printf("Remove usb device: CLASS(0x%x) SUBCLASS(0x%x) iSerialNumber(0x%x)\n",
desc.bDeviceClass, desc.bDeviceSubClass, desc.iSerialNumber);
return 0;
}
int LibUSBControl::init_libusb(void)
{
libusb_hotplug_callback_handle usb_arrived_handle;
libusb_hotplug_callback_handle usb_left_handle;
libusb_hotplug_flag flag = static_cast<libusb_hotplug_flag>(1);
int rv = 0;
rv = libusb_init(&ctx);
rv = libusb_hotplug_register_callback(ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
flag, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY, usb_arrived_callback, NULL, &usb_arrived_handle);
if (LIBUSB_SUCCESS != rv) {
printf("注册USB热插拔失败! \n");
libusb_exit(ctx);
return EXIT_FAILURE;
}
rv = libusb_hotplug_register_callback(ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
flag, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY, usb_left_callback, NULL, &usb_left_handle);
if (LIBUSB_SUCCESS != rv) {
printf("注册USB热插拔失败! \n");
libusb_exit(ctx);
return EXIT_FAILURE;
}
libusb_hotplug_deregister_callback(ctx, usb_arrived_handle);
libusb_hotplug_deregister_callback(ctx, usb_left_handle);
auto th = new std::thread(hotplugin);
th->detach();
return rv;
}
6.usb初始化
int LibUSBControl::openDevice(int pid, int vid)
{
user_device.idProduct = pid;
user_device.idVendor = vid ;
int ret = init_libusb();
user_device.outEndPoint = 0x00;
ret = libusb_kernel_driver_active(g_usb_handle, user_device.outEndPoint);
if(ret == 1){
/// 卸载驱动
ret = libusb_detach_kernel_driver(g_usb_handle, user_device.outEndPoint);
if(ret < 0){
qDebug("libusb libusb_detach_kernel_driver_np #0: %s", libusb_error_name(ret));
}
}
/// 为指定的设备申请接口,bInterfaceNumber
if ((ret=libusb_claim_interface(g_usb_handle, user_device.outEndPoint)) < 0) { //设置usb设备接口为0
qDebug("error claiming interface #0: %s", libusb_error_name(ret));
}
/// 后台去查
std::thread([this](){
while (user_device.isOpen) {
thread_callback();
std::this_thread::sleep_for( std::chrono::milliseconds(user_device.ms_Request) ) ;
}
}).detach();
return ret;
}
7.数据读取
/// 后台线程查询中断
void LibUSBControl::thread_callback()
{
int length ,rv= 0;
UC _readbuff[HID_PROTO_LEN];
memset(_readbuff,0,sizeof(_readbuff));
//读中断端点1,HID,此3D摇杆使用中断读取模式
rv=libusb_interrupt_transfer(g_usb_handle,HID_ENDPOINT_IN,_readbuff,sizeof(_readbuff),&length,0);
if((rv < 0)){
qDebug()<<libusb_error_name(rv);
}else {
std::string recv;
for(int i = 0;i < sizeof(_readbuff);i++){
recv.push_back(UC(_readbuff[i]));
}
_sigUpdate(recv);
}
}

本文深入探讨了使用libusb库进行USB设备交互的过程,包括设备枚举、数据传输、中断读取及热插拔事件处理。重点讲解了如何通过libusb初始化设备、配置接口和端点,实现数据的异步读取,并提供了详细的代码示例。
4801

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



