summaryrefslogtreecommitdiffhomepage
path: root/video-ps3eye/PS3EYEDriver/singleton.cpp
blob: 93017fc517258d78e65609ace2077cca18286611 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include "singleton.hpp"
#include "internal.hpp"
#include "ps3eye.hpp"

//#define USE_CONTEXT

USBMgr::USBMgr()
{
#ifdef USE_CONTEXT
    libusb_init(&usb_context);
#else
    libusb_init(nullptr);
#endif
    libusb_set_debug(usb_context, 3);
}

USBMgr::~USBMgr()
{
#ifdef USE_CONTEXT
    stop_xfer_thread();
    libusb_exit(usb_context);
#endif
}

USBMgr& USBMgr::instance()
{
    static USBMgr ret;
    return ret;
}

void USBMgr::camera_started()
{
    if (++active_camera_count == 1)
        start_xfer_thread();
}

void USBMgr::camera_stopped()
{
    if (--active_camera_count == 0)
        stop_xfer_thread();
}

void USBMgr::start_xfer_thread()
{
    update_thread = std::thread(&USBMgr::transfer_loop, this);
}

void USBMgr::stop_xfer_thread()
{
    exit_signaled = true;
    update_thread.join();
    // Reset the exit signal flag.
    // If we don't and we call start_xfer_thread() again, transfer_loop will exit immediately.
    exit_signaled = false;
}

void USBMgr::transfer_loop()
{
    struct timeval tv {
        0,
        50 * 1000, // ms
    };

    debug2("-> xfer loop");

    while (!exit_signaled.load(std::memory_order_relaxed))
    {
        int status = libusb_handle_events_timeout_completed(usb_context, &tv, nullptr);

        if (status != LIBUSB_SUCCESS && status != LIBUSB_ERROR_INTERRUPTED)
            debug("libusb error(%d) %s\n", status, libusb_strerror((enum libusb_error)status));
    }
    debug2("<- xfer loop\n");
}

int USBMgr::list_devices(std::vector<ps3eye_camera::device>& list)
{
    libusb_device **devs;
    libusb_device_handle *devhandle;
    int cnt = (int)libusb_get_device_list(usb_context, &devs);

    if (cnt < 0)
        debug("device scan failed\n");

    cnt = 0;
    for (int i = 0; devs[i]; i++)
    {
        libusb_device* dev = devs[i];
        struct libusb_device_descriptor desc;

        if (libusb_get_device_descriptor(dev, &desc))
            continue;
        if (desc.idVendor == ps3eye_camera::VENDOR_ID && desc.idProduct == ps3eye_camera::PRODUCT_ID)
        {
            if (libusb_open(dev, &devhandle))
                continue;
            libusb_ref_device(dev);
            libusb_close(devhandle);
            list.emplace_back(std::make_shared<ps3eye_camera>(dev));
            cnt++;
        }
    }

    libusb_free_device_list(devs, 1);

    return cnt;
}