使用libusb库实时监测usb设备插拔信息

2 篇文章 0 订阅

使用libusb库实时监测usb设备插拔信息,信息包括USB插拔状态、USB接口号、设备名称iProduct、厂商名称iManufacturer、设备编号idProduct、厂商编号idVendor、接口编号、USB类型码bDeviceClass,与lsusb -v所获取的信息一致,接口号与lsusb -t显示信息一致,厂商名称id为0时,名称获取不到,用厂商编号填充。

class LibusbContext {
public:
    LibusbContext() {
        ctx=NULL;
        libusb_init(&ctx);
    }

    ~LibusbContext() {
        libusb_exit(ctx);
    }

    libusb_context *get() {
        return ctx;
    }

private:
    libusb_context *ctx;
};

struct usb_info
{
    // USB接口号
    //std::string usbNum;

    //设备名称
    //std::string iProduct;

    //厂商名称
    // std::string iManufacturer;

    /** 设备编号 */
    uint16_t idProduct;
    /** 厂商编号 */
    uint16_t idVendor;

    // USB接口号
    //std::string Interface;

    uint8_t bDeviceClass;

    std::string msg;
};
map<unsigned short, usb_info> usbList;
string get_device(libusb_device *dev)
{
    std::string str;
    libusb_device_handle *handle = NULL;
    libusb_device_descriptor desc;
    libusb_get_device_descriptor(dev, &desc);

    int result = libusb_open(dev, &handle);
    if (result != LIBUSB_SUCCESS) {
        // 处理错误
        return str;
    }
    sleep(1);

    unsigned char iProduct[256]={0};
    unsigned char iManufacturer[256]={0};
    int ret;

    if (desc.bDeviceClass == 0) {
        libusb_config_descriptor *config;
        libusb_get_config_descriptor(dev, 0, &config);

        printf("bNumInterfaces:%d\n",config->bNumInterfaces);
        for (int i = 0; i < config->bNumInterfaces; i++)
        {
            const libusb_interface *inter = &config->interface[i];
            const libusb_interface_descriptor *interdesc = &inter->altsetting[0];
            printf("Interface Class Code: %d\n", interdesc->bInterfaceClass);
            desc.bDeviceClass = interdesc->bInterfaceClass;
        }
        libusb_free_config_descriptor(config);
    }

    ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, iProduct, sizeof(iProduct));
    if ( ret<= 0 ) {
        printf("iProduct: err %x %s\n",desc.iProduct,libusb_error_name(ret));//设备名称iProduct
        sprintf((char*)iProduct,"%04x",desc.iProduct);
    }
    ret = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, iManufacturer, sizeof(iManufacturer));
    if (ret <= 0 || iManufacturer[0] == ' ') {
        printf("Manufacturer:err %x %s\n", desc.iManufacturer,libusb_error_name(ret));//厂商名称iManufacturer
        sprintf((char*)iManufacturer,"%04x",desc.idVendor);
    }

    char usbNum[128]={0};
    uint8_t path[8];
    char port[16]={0};
    int r = libusb_get_port_numbers(dev,path, sizeof(path));
    if (r > 0) {
        for (int j = 0; j < r; j++) {
            char temp[4];
            sprintf(temp, "%d.", path[j]);
            strcat(port, temp);
        }
        port[strlen(port) - 1] = '\0'; // 移除末尾的点
        printf("port: %s\n", port);
    }

    sprintf(usbNum,"{%x-%c}", libusb_get_bus_number(dev),port[0]);
    str+=usbNum;

    char minfo[128]={0};
    sprintf(minfo,"{%s}{%s}{%04x}{%04x}", iProduct,iManufacturer,desc.idProduct,desc.idVendor);
    str+=minfo;

    char intf[128]={0};
    sprintf(intf,"<%x-%s:%x.0@%02x>", libusb_get_bus_number(dev),port/* libusb_get_port_number(dev)*/,
            desc.bNumConfigurations,desc.bDeviceClass);
    str+=intf;

    //desc.idVendor
    usb_info info = {desc.idProduct,desc.idVendor,desc.bDeviceClass,str};
    usbList.insert(map<unsigned short, usb_info>::value_type(desc.idVendor,info));

    libusb_close(handle);
    return str;
}

int hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
    struct libusb_device_descriptor desc;
    (void)libusb_get_device_descriptor(dev, &desc);

    //usbMonitor* usbptr = static_cast<usbMonitor*>(user_data);
    map<unsigned short, usb_info>::iterator it = usbList.find(desc.idVendor);

    int flag = 0;
    std::string info;

    if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)
    {
        flag = 1;
        if(it != usbList.end())
        {
            printf("设备已插入:%s\n",it->second.msg.c_str());
            info = it->second.msg.c_str();
        }
        else
        {
            libusb_device **devs;
            ssize_t cnt;
            LibusbContext ctx;

            cnt = libusb_get_device_list(ctx.get(), &devs);//USB设备列表
            if(cnt < 0) {
                printf("Get Device Error\n");
                return 0;
            }

            for(ssize_t i = 0; i < cnt; i++) {
                if(libusb_get_bus_number(dev) == libusb_get_bus_number(devs[i]) &&
                        libusb_get_device_address(dev) == libusb_get_device_address(devs[i]))
                {
                    info = get_device(devs[i]);
                    if(info.empty())return  0;
                    printf("设备已插入:%s\n",info.c_str());
                    it = usbList.find(desc.idVendor);
                    break;
                }
            }
            libusb_free_device_list(devs, 1);
        }
    }
    else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)
    {
        flag = 2;
        if(it == usbList.end())
        {
            printf("已拔出\n");
            return 0;
        }
        else
        {
            info = it->second.msg;
            usbList.erase(it);
            printf("设备已拔出:%s\n",info.c_str());
        }
    }
    printf("type:%02x\n",it->second.bDeviceClass);
    return 0;
}

void startMonitor()
{
    if(libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) == 0)//检查当前运行的libusb库是否支持热插拔功能的函数调用
    {
        printf("libusb不支持热插拔\n");
    }

    LibusbContext ctx;
    if (!ctx.get()) {
        printf("Failed to initialize libusb\n");
        return ;
    }

    libusb_hotplug_register_callback(ctx.get(), (libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED|LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) ,
                                     LIBUSB_HOTPLUG_NO_FLAGS, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
                                     LIBUSB_HOTPLUG_MATCH_ANY, (libusb_hotplug_callback_fn)hotplug_callback, NULL,NULL);
    // 主循环
    int result;
    bool running = true;
    while (running)
    {
        timeval tv = {0, 1000};  // 设置超时时间为1000毫秒
        result = libusb_handle_events_timeout_completed(ctx.get(), &tv, NULL);
    }
    return ;
}

int main1() {
    const struct libusb_version *version;
    version = libusb_get_version();
    std::cout << "libusb version: " << version->major << "." << version->minor << "." << version->micro << std::endl;
    
    startMonitor();
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值