libusb-qt-linux-hid技术

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

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);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值