MiSo1289 / usb-asio

Libusb wrapper for Asio
MIT License
63 stars 5 forks source link
asio cpp cpp20 cpp20-library libusb usb

usb-asio

A libusb wrapper for Asio. Header-only, supports both standalone and boost versions of Asio. Requires a C++20 compiler (only tested on gcc-10). This is an early version, some features might not work as expected.

Using with standalone Asio

By default, boost version of Asio is used. To use standalone asio:

auto main() -> int { auto ctx = asio::io_context{};

auto future = asio::co_spawn(
    ctx.get_executor(),
    [&]() -> asio::awaitable<int> {
        auto dev = usb_asio::usb_device{ctx};

        for (auto const& dev_info : usb_asio::list_usb_devices(ctx))
        {
            auto const desc = dev_info.device_descriptor();
            if (desc.idVendor == 0xABCDu && desc.idProduct == 0x1234u)
            {
                dev.open(dev_info);
            }
        }

        if (dev.is_open())
        {
            auto const interface_number = std::uint8_t{1};
            // Claim the interface
            auto interface = usb_asio::usb_interface{
                dev, interface_number};

            auto const alt_setting_number = std::uint8_t{2};
            // Set interface alt setting
            co_await interface.async_set_alt_setting(
                alt_setting_number, asio::use_awaitable);

            auto const endpoint_number = std::uint8_t{3};
            auto const timeout = std::chrono::seconds{1};
            auto transfer = usb_asio::usb_in_bulk_transfer{
                dev, endpoint_number, timeout};

            auto buff = std::array<char, 512>{};
            // Read from the bulk endpoint 
            auto const n = co_await transfer.async_read_some(
                asio::buffer(buff), asio::use_awaitable);

            std::cout << std::string_view{buff.data(), n} << "\n";

            // Unclaim the interface (otherwise the destructor would
            // do this synchronously, blocking the executor).
            // If you do not care about resetting the interface,
            // you can call interface.release() instead.
            co_await interface.async_unclaim(asio::use_awaitable);

            co_return EXIT_SUCCESS;
        }

        co_return EXIT_FAILURE;
    },
    asio::use_future);

ctx.run();

return future.get();

}