| // Copyright 2024 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #pragma once |
| #include <libusb-1.0/libusb.h> |
| |
| #include <stdplus/handle/managed.hpp> |
| |
| #include <chrono> |
| #include <cstdint> |
| #include <utility> |
| #include <vector> |
| |
| // NOLINTNEXTLINE(cert-dcl58-cpp) |
| namespace google |
| { |
| namespace hoth |
| { |
| |
| class LibusbIntf |
| { |
| public: |
| virtual ~LibusbIntf() = default; |
| |
| virtual int release_interface(libusb_device_handle* handle, |
| int interface_num) = 0; |
| virtual int claim_interface(libusb_device_handle* handle, |
| int interface_num) = 0; |
| virtual int bulk_transfer(libusb_device_handle* dev_handle, |
| unsigned char endpoint, unsigned char* data, |
| int length, int* transferred, |
| unsigned int timeout) = 0; |
| virtual void close(libusb_device_handle* dev_handle) = 0; |
| virtual int |
| get_active_config_descriptor(libusb_device* dev, |
| libusb_config_descriptor** config) = 0; |
| virtual int get_bus_number(libusb_device* dev) = 0; |
| virtual int get_port_numbers(libusb_device* dev, uint8_t* port_numbers, |
| int port_numbers_len) = 0; |
| virtual int open(libusb_device* dev, libusb_device_handle** handle) = 0; |
| virtual libusb_device* ref_device(libusb_device* dev) = 0; |
| virtual void unref_device(libusb_device* dev) = 0; |
| virtual ssize_t get_device_list(libusb_context* ctx, |
| libusb_device*** list) = 0; |
| virtual void free_device_list(libusb_device** list, int unref_devices) = 0; |
| virtual void exit(libusb_context* ctx) = 0; |
| virtual int init(libusb_context** ctx) = 0; |
| }; |
| |
| namespace libusb |
| { |
| |
| static constexpr uint8_t kTransferTypeBits = 0x03; |
| static constexpr uint8_t kAddressDirectionBits = 0x80; |
| |
| class InterfaceClaim |
| { |
| public: |
| InterfaceClaim(LibusbIntf* libusb, libusb_device_handle* handle, |
| int interface); |
| |
| private: |
| static void drop(libusb_device_handle*&& handle, int& interface, |
| LibusbIntf*& libusb); |
| libusb_device_handle* init(libusb_device_handle* handle, int interface); |
| |
| LibusbIntf* libusb; |
| stdplus::Managed<libusb_device_handle*, int, LibusbIntf*>::Handle<drop> |
| handle; |
| }; |
| |
| class DeviceHandle |
| { |
| public: |
| DeviceHandle(LibusbIntf* libusb, libusb_device_handle* handle) : |
| libusb(libusb), handle(handle, libusb) |
| {} |
| InterfaceClaim claim_interface(int interface); |
| unsigned bulk_transfer(const libusb_endpoint_descriptor& ep, uint8_t* data, |
| size_t size, std::chrono::milliseconds timeout); |
| |
| private: |
| static void drop(libusb_device_handle*&& handle, LibusbIntf*& libusb); |
| |
| LibusbIntf* libusb; |
| stdplus::Managed<libusb_device_handle*, LibusbIntf*>::Handle<drop> handle; |
| }; |
| |
| class Device |
| { |
| public: |
| Device(LibusbIntf* libusb, libusb_device* dev) : |
| libusb(libusb), dev(dev, libusb) |
| {} |
| libusb_config_descriptor& get_active_config_descriptor(); |
| uint8_t get_bus_number(); |
| std::vector<uint8_t> get_port_numbers(); |
| DeviceHandle open(); |
| |
| private: |
| static void drop(libusb_device*&& dev, LibusbIntf*& libusb); |
| |
| LibusbIntf* libusb; |
| stdplus::Managed<libusb_device*, LibusbIntf*>::Handle<drop> dev; |
| }; |
| |
| class Context |
| { |
| public: |
| explicit Context(LibusbIntf* libusb) : libusb(libusb), ctx(init(), libusb) |
| {} |
| std::vector<Device> get_device_list(); |
| |
| private: |
| libusb_context* init(); |
| static void drop(libusb_context*&& ctx, LibusbIntf*& libusb); |
| |
| LibusbIntf* libusb; |
| stdplus::Managed<libusb_context*, LibusbIntf*>::Handle<drop> ctx; |
| }; |
| |
| } // namespace libusb |
| } // namespace hoth |
| } // namespace google |