如何强制libusb事件以便libusb_handle_events()返回

时间:2017-08-14 10:40:39

标签: libusb

假设我有一个只使用hotplug API的libusb程序。你注册了一个回调,然后显然必须在循环中调用libusb_handle_events(),然后调用你的hotplug回调。

int LIBUSB_CALL hotplugCallback(libusb_context* ctx,
                                libusb_device* device,
                                libusb_hotplug_event event,
                                void* user_data)
{
    cout << "Device plugged in or unplugged";
}

void main()
{
    libusb_init(nullptr);

    libusb_hotplug_register_callback(nullptr,
                                    static_cast<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,
                                    &hotplugCallback,
                                    this,
                                    &hotplugCallbackHandle);

    for (;;)
    {
        if (libusb_handle_events_completed(nullptr, nullptr) != LIBUSB_SUCCESS)
            return 1;
    }

    return 0;
}

问题是,没有超时黑客如何彻底退出此事件循环?我无法找到任何强制libusb_handle_events()(或libusb_handle_events_completed())返回的函数。理论上他们可能永远不会回来。

3 个答案:

答案 0 :(得分:4)

对不起,如果迟到了。

本来可以更好地表达该问​​题,但我假设(根据您的评论更新)您的实际程序类似于以下内容:

int LIBUSB_CALL hotplugCallback(libusb_context *ctx,
                                libusb_device *device,
                                libusb_hotplug_event event,
                                void *user_data) {
    cout << "Device plugged in or unplugged";
}

void SomeClass::someFunction() {
    libusb_init(nullptr);
    libusb_hotplug_register_callback(nullptr,
                                static_cast<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,
                                &hotplugCallback,
                                this,
                                &hotplugCallbackHandle);

    this->thread = std::thread([this]() {
        while (this->handlingEvents) {
            int error = libusb_handle_events_completed(context, nullptr);
        }
    });
}

比方说,您的对象已被释放,并且无论USB总线上发生了什么,您都不在乎,您想清理线程。

您求反this->handlingEvents,然后调用thread.join(),线程挂起60秒,然后恢复执行。

之所以这样做,是因为libusb_handle_events_completed的默认行为会调用libusb_handle_events_timeout_completed,并在60秒的超时间隔内传递并计划使其无限。

强制执行的方式 libusb_handle_events_completed 返回是您叫libusb_hotplug_deregister_callback,它将唤醒libusb_handle_events(),从而使函数返回

docs中有关于此行为的更多信息。

因此您的类的析构函数(或您想立即停止监听的任何地方)可能看起来像这样:

SomeClass::~SomeClass() {
    this->handlingEvents = false;
    libusb_hotplug_deregister_callback(context, hotplugCallbackHandle);
    if (this->thread.joinable()) this->thread.join();

    libusb_exit(this->context);
}

答案 1 :(得分:0)

在功能中:

int libusb_handle_events_completed(libusb_context* ctx, int* completed) 

您可以将已完成的值更改为&#34; 1&#34;所以函数将无阻塞地返回

根据他们的文件:

  

如果参数complete不是NULL,则在获取事件后   处理锁定此函数将立即返回整数   指向不是0.这允许无竞赛等待   完成特定的转移。

答案 2 :(得分:0)

libusb中没有强制libusb_handle_events()返回的函数。

建议在专用线程中使用libusb_handle_events(),以免您的主线程被此调用阻塞。即使,如果您需要操纵事件处理程序的调用,也可以将调用置于while(condition)并在主线程中更改条件状态。

Libusb文档详细介绍了此here