<commit_before>#include "uvc.h"

#ifndef WIN32
#include "libuvc/libuvc.h"
#include "libuvc/libuvc_internal.h" // For LibUSB punchthrough

#include <thread>

namespace rsimpl
{
    namespace uvc
    {
        static void check(const char * call, uvc_error_t status)
        {
            if (status < 0) throw std::runtime_error(to_string() << call << "(...) returned " << uvc_strerror(status));
        }
        #define CALL_UVC(name, ...) check(#name, name(__VA_ARGS__))

        struct device_id { int vid, pid; std::string serial_no; };

        std::vector<device_id> enumerate_devices(uvc_context * context)
        {
            std::vector<device_id> refs;
            uvc_device_t ** list;
            CALL_UVC(uvc_get_device_list, context, &list);
            for(auto it = list; *it; ++it)
            {
                uvc_device_descriptor_t * desc;
                CALL_UVC(uvc_get_device_descriptor, *it, &desc);
                refs.push_back({desc->idVendor, desc->idProduct, desc->serialNumber});
                uvc_free_device_descriptor(desc);
            }
            uvc_free_device_list(list, 1);
            return refs;
        }

        uvc_device_t * create_device(uvc_context * context, const device_id & ref)
        {
            uvc_device_t * device = nullptr;
            uvc_device_t ** list;
            CALL_UVC(uvc_get_device_list, context, &list);
            for(auto it = list; *it; ++it)
            {
                uvc_device_descriptor_t * desc;
                CALL_UVC(uvc_get_device_descriptor, *it, &desc);
                if(desc->idVendor == ref.vid && desc->idProduct == ref.pid && desc->serialNumber == ref.serial_no)
                {
                    device = *it;
                    uvc_ref_device(device);
                }
                uvc_free_device_descriptor(desc);
                if(device) break;
            }
            uvc_free_device_list(list, 1);
            return device;
        }

        struct context_ref::_impl
        {
            uvc_context_t * ctx;

            _impl() : ctx() { check("uvc_init", uvc_init(&ctx, nullptr)); }
            ~_impl() { if(ctx) uvc_exit(ctx); }
        };

        struct subdevice
        {
            uvc_device_handle_t * handle = nullptr;
            uvc_stream_ctrl_t ctrl;
            std::function<void(const void * frame)> callback;
        };

        struct device_ref::_impl
        {
            std::shared_ptr<context_ref::_impl> parent;
            device_id id;
            uvc_device_t * device;
            std::vector<subdevice> subdevices;
            std::vector<int> claimed_interfaces;

            _impl() : device() {}
            _impl(std::shared_ptr<context_ref::_impl> parent, device_id id) : _impl()
            {
                this->parent = parent;
                this->id = id;
                this->device = create_device(parent->ctx, id);
            }
            ~_impl()
            {
                for(auto interface_number : claimed_interfaces)
                {
                    int status = libusb_release_interface(get_subdevice(0).handle->usb_devh, interface_number);
                    if(status < 0) DEBUG_ERR("libusb_release_interface(...) returned " << libusb_error_name(status));
                }

                for(auto & sub : subdevices) if(sub.handle) uvc_close(sub.handle);
                if(device) uvc_unref_device(device);
            }

            subdevice & get_subdevice(int subdevice_index)
            {
                if(subdevice_index >= subdevices.size()) subdevices.resize(subdevice_index+1);
                if(!subdevices[subdevice_index].handle) check("uvc_open2", uvc_open2(device, &subdevices[subdevice_index].handle, subdevice_index));
                return subdevices[subdevice_index];
            }
        };

        ////////////
        // device //
        ////////////

        int device_ref::get_vendor_id() const { return impl->id.vid; }
        int device_ref::get_product_id() const { return impl->id.pid; }

        void device_ref::get_control(uint8_t unit, uint8_t ctrl, void * data, int len) const
        {
            int status = uvc_get_ctrl(impl->get_subdevice(0).handle, unit, ctrl, data, len, UVC_GET_CUR);
            if(status < 0) throw std::runtime_error(to_string() << "uvc_get_ctrl(...) returned " << libusb_error_name(status));
        }

        void device_ref::set_control(uint8_t unit, uint8_t ctrl, void * data, int len) const
        {
            int status = uvc_set_ctrl(impl->get_subdevice(0).handle, unit, ctrl, data, len);
            if(status < 0) throw std::runtime_error(to_string() << "uvc_set_ctrl(...) returned " << libusb_error_name(status));
        }

        void device_ref::claim_interface(const guid & interface_guid, int interface_number) const
        {
            int status = libusb_claim_interface(impl->get_subdevice(0).handle->usb_devh, interface_number);
            if(status < 0) throw std::runtime_error(to_string() << "libusb_claim_interface(...) returned " << libusb_error_name(status));
            impl->claimed_interfaces.push_back(interface_number);
        }

        void device_ref::bulk_transfer(unsigned char endpoint, void * data, int length, int *actual_length, unsigned int timeout) const
        {
            int status = libusb_bulk_transfer(impl->get_subdevice(0).handle->usb_devh, endpoint, (unsigned char *)data, length, actual_length, timeout);
            if(status < 0) throw std::runtime_error(to_string() << "libusb_bulk_transfer(...) returned " << libusb_error_name(status));
        }

        void device_ref::set_subdevice_mode(int subdevice_index, int width, int height, uint32_t fourcc, int fps, std::function<void(const void * frame)> callback) const
        {
            auto & sub = impl->get_subdevice(subdevice_index);
            check("get_stream_ctrl_format_size", uvc_get_stream_ctrl_format_size(sub.handle, &sub.ctrl, reinterpret_cast<const big_endian<uint32_t> &>(fourcc), width, height, fps));
            sub.callback = callback;
        }

        void device_ref::start_streaming() const
        {
            for(auto & sub : impl->subdevices)
            {
                if(sub.callback)
                {
                    #if defined (ENABLE_DEBUG_SPAM)
                    uvc_print_stream_ctrl(&sub.ctrl, stdout);
                    #endif

                    check("uvc_start_streaming", uvc_start_streaming(sub.handle, &sub.ctrl, [](uvc_frame * frame, void * user)
                    {
                        reinterpret_cast<subdevice *>(user)->callback(frame->data);
                    }, &sub, 0));
                }
            }
        }

        void device_ref::stop_streaming() const
        {
            // Stop all streaming
            for(auto & sub : impl->subdevices)
            {
                if(sub.handle) uvc_stop_streaming(sub.handle);
                sub.ctrl = {};
                sub.callback = {};
            }

            // SW reset
            if(impl->id.pid == 2688)
            {
                uint8_t reset = 1;
                const int CAMERA_XU_UNIT_ID = 2;
                const int CONTROL_SW_RESET = 16;
                uvc_set_ctrl(impl->get_subdevice(0).handle, CAMERA_XU_UNIT_ID, CONTROL_SW_RESET, &reset, sizeof(reset));
            }

            // NOTE: We are explicitly NOT calling uvc_close(...) for each subdevice handle
            for(auto & sub : impl->subdevices) sub.handle = nullptr;

            // Attempt to recreate the device
            uvc_unref_device(impl->device);
            std::this_thread::sleep_for(std::chrono::seconds(2));
            impl->device = create_device(impl->parent->ctx, impl->id);
            if(!impl->device) throw std::runtime_error("software reset failed");
        }

        /////////////
        // context //
        /////////////

        context_ref create_context()
        {
            return {std::make_shared<context_ref::_impl>()};
        }

        std::vector<device_ref> context_ref::query_devices() const
        {
            std::vector<device_ref> devices;
            for(auto id : enumerate_devices(impl->ctx)) devices.push_back({std::make_shared<device_ref::_impl>(impl, id)});
            return devices;
        }
    }
}
<commit_msg>Restore Linux build<commit_after>#include "uvc.h"

#ifndef WIN32
#include "libuvc/libuvc.h"
#include "libuvc/libuvc_internal.h" // For LibUSB punchthrough

#include <thread>

namespace rsimpl
{
    namespace uvc
    {
        static void check(const char * call, uvc_error_t status)
        {
            if (status < 0) throw std::runtime_error(to_string() << call << "(...) returned " << uvc_strerror(status));
        }
        #define CALL_UVC(name, ...) check(#name, name(__VA_ARGS__))

        struct device_id { int vid, pid; std::string serial_no; };

        std::vector<device_id> enumerate_devices(uvc_context * context)
        {
            std::vector<device_id> refs;
            uvc_device_t ** list;
            CALL_UVC(uvc_get_device_list, context, &list);
            for(auto it = list; *it; ++it)
            {
                uvc_device_descriptor_t * desc;
                CALL_UVC(uvc_get_device_descriptor, *it, &desc);
                refs.push_back({desc->idVendor, desc->idProduct, desc->serialNumber});
                uvc_free_device_descriptor(desc);
            }
            uvc_free_device_list(list, 1);
            return refs;
        }

        uvc_device_t * create_device(uvc_context * context, const device_id & ref)
        {
            uvc_device_t * device = nullptr;
            uvc_device_t ** list;
            CALL_UVC(uvc_get_device_list, context, &list);
            for(auto it = list; *it; ++it)
            {
                uvc_device_descriptor_t * desc;
                CALL_UVC(uvc_get_device_descriptor, *it, &desc);
                if(desc->idVendor == ref.vid && desc->idProduct == ref.pid && desc->serialNumber == ref.serial_no)
                {
                    device = *it;
                    uvc_ref_device(device);
                }
                uvc_free_device_descriptor(desc);
                if(device) break;
            }
            uvc_free_device_list(list, 1);
            return device;
        }

        struct context
        {
            uvc_context_t * ctx;

            context() : ctx() { check("uvc_init", uvc_init(&ctx, nullptr)); }
            ~context() { if(ctx) uvc_exit(ctx); }
        };

        struct subdevice
        {
            uvc_device_handle_t * handle = nullptr;
            uvc_stream_ctrl_t ctrl;
            std::function<void(const void * frame)> callback;
        };

        struct device
        {
            const std::shared_ptr<context> parent;
            const device_id id;
            uvc_device_t * uvcdevice;
            std::vector<subdevice> subdevices;
            std::vector<int> claimed_interfaces;

            device(std::shared_ptr<context> parent, device_id id) : parent(parent), id(id)
            {
                uvcdevice = create_device(parent->ctx, id);
                get_subdevice(0);
            }
            ~device()
            {
                for(auto interface_number : claimed_interfaces)
                {
                    int status = libusb_release_interface(get_subdevice(0).handle->usb_devh, interface_number);
                    if(status < 0) DEBUG_ERR("libusb_release_interface(...) returned " << libusb_error_name(status));
                }

                for(auto & sub : subdevices) if(sub.handle) uvc_close(sub.handle);
                if(uvcdevice) uvc_unref_device(uvcdevice);
            }

            subdevice & get_subdevice(int subdevice_index)
            {
                if(subdevice_index >= subdevices.size()) subdevices.resize(subdevice_index+1);
                if(!subdevices[subdevice_index].handle) check("uvc_open2", uvc_open2(uvcdevice, &subdevices[subdevice_index].handle, subdevice_index));
                return subdevices[subdevice_index];
            }

            uvc_device_handle_t * get_control_handle() const
            {
                if(subdevices.empty() || !subdevices[0].handle) throw std::runtime_error("unable to get control handle");
                return subdevices[0].handle;
            }
        };

        ////////////
        // device //
        ////////////

        int get_vendor_id(const device & device) { return device.id.vid; }
        int get_product_id(const device & device) { return device.id.pid; }

        void get_control(const device & device, uint8_t unit, uint8_t ctrl, void * data, int len)
        {
            int status = uvc_get_ctrl(device.get_control_handle(), unit, ctrl, data, len, UVC_GET_CUR);
            if(status < 0) throw std::runtime_error(to_string() << "uvc_get_ctrl(...) returned " << libusb_error_name(status));
        }

        void set_control(device & device, uint8_t unit, uint8_t ctrl, void * data, int len)
        {
            int status = uvc_set_ctrl(device.get_control_handle(), unit, ctrl, data, len);
            if(status < 0) throw std::runtime_error(to_string() << "uvc_set_ctrl(...) returned " << libusb_error_name(status));
        }

        void claim_interface(device & device, const guid & interface_guid, int interface_number)
        {
            int status = libusb_claim_interface(device.get_control_handle()->usb_devh, interface_number);
            if(status < 0) throw std::runtime_error(to_string() << "libusb_claim_interface(...) returned " << libusb_error_name(status));
            device.claimed_interfaces.push_back(interface_number);
        }

        void bulk_transfer(device & device, unsigned char endpoint, void * data, int length, int *actual_length, unsigned int timeout)
        {
            int status = libusb_bulk_transfer(device.get_control_handle()->usb_devh, endpoint, (unsigned char *)data, length, actual_length, timeout);
            if(status < 0) throw std::runtime_error(to_string() << "libusb_bulk_transfer(...) returned " << libusb_error_name(status));
        }

        void set_subdevice_mode(device & device, int subdevice_index, int width, int height, uint32_t fourcc, int fps, std::function<void(const void * frame)> callback)
        {
            auto & sub = device.get_subdevice(subdevice_index);
            check("get_stream_ctrl_format_size", uvc_get_stream_ctrl_format_size(sub.handle, &sub.ctrl, reinterpret_cast<const big_endian<uint32_t> &>(fourcc), width, height, fps));
            sub.callback = callback;
        }

        void start_streaming(device & device)
        {
            for(auto & sub : device.subdevices)
            {
                if(sub.callback)
                {
                    #if defined (ENABLE_DEBUG_SPAM)
                    uvc_print_stream_ctrl(&sub.ctrl, stdout);
                    #endif

                    check("uvc_start_streaming", uvc_start_streaming(sub.handle, &sub.ctrl, [](uvc_frame * frame, void * user)
                    {
                        reinterpret_cast<subdevice *>(user)->callback(frame->data);
                    }, &sub, 0));
                }
            }
        }

        void stop_streaming(device & device)
        {
            // Stop all streaming
            for(auto & sub : device.subdevices)
            {
                if(sub.handle) uvc_stop_streaming(sub.handle);
                sub.ctrl = {};
                sub.callback = {};
            }

            // SW reset
            if(device.id.pid == 2688)
            {
                uint8_t reset = 1;
                const int CAMERA_XU_UNIT_ID = 2;
                const int CONTROL_SW_RESET = 16;
                uvc_set_ctrl(device.get_subdevice(0).handle, CAMERA_XU_UNIT_ID, CONTROL_SW_RESET, &reset, sizeof(reset));
            }

            // NOTE: We are explicitly NOT calling uvc_close(...) for each subdevice handle
            for(auto & sub : device.subdevices) sub.handle = nullptr;

            // Attempt to recreate the device
            uvc_unref_device(device.uvcdevice);
            std::this_thread::sleep_for(std::chrono::seconds(2));
            device.uvcdevice = create_device(device.parent->ctx, device.id);
            if(!device.uvcdevice) throw std::runtime_error("software reset failed");
            device.get_subdevice(0);
        }

        /////////////
        // context //
        /////////////

        std::shared_ptr<context> create_context()
        {
            return std::make_shared<context>();
        }

        std::vector<std::shared_ptr<device>> query_devices(std::shared_ptr<context> context)
        {
            std::vector<std::shared_ptr<device>> devices;
            for(auto id : enumerate_devices(context->ctx)) devices.push_back(std::make_shared<device>(context, id));
            return devices;
        }
    }
}

{'fraction_non_alphanumeric': 0.11774461028192372, 'fraction_numerical': 0.0045013030087656955, 'mean_word_length': 1.9112068965517242, 'pattern_counts': {'":': 0, '<': 99, '<?xml version=': 0, '>': 90, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2698237', 'n_tokens_mistral': 5042, 'n_tokens_neox': 4833, 'n_words': 898}