libusb-qt-linux-hid技術

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章