Files
pip/libs/main/io_devices/piusb.h
2026-03-12 14:46:57 +03:00

415 lines
18 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! \~\file piusb.h
//! \~\ingroup USB
//! \~\brief
//! \~english USB input/output device declarations
//! \~russian Объявления USB-устройства ввода/вывода
/*
PIP - Platform Independent Primitives
USB, based on libusb
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup USB USB
//! \~\brief
//! \~english USB support via libusb
//! \~russian Поддержка USB с помощью libusb
//!
//! \~\details
//! \~english \section cmake_module_USB Building with CMake
//! \~russian \section cmake_module_USB Сборка с использованием CMake
//!
//! \~\code
//! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP::USB)
//! \endcode
//!
//! \~english \par Common
//! \~russian \par Общее
//!
//! \~english
//! This module declares raw USB input/output devices built on libusb.
//!
//! \~russian
//! Модуль объявляет USB-устройства ввода/вывода для сырого обмена на базе libusb.
//!
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//!
#ifndef PIUSB_H
#define PIUSB_H
#include "piiodevice.h"
#include "pip_usb_export.h"
struct usb_dev_handle;
//! \~\ingroup USB
//! \~\brief
//! \~english USB implementation of \a PIIODevice.
//! \~russian USB-реализация \a PIIODevice.
//! \~\details
//! \~english The PIUSB class provides functionality for working with USB devices through the libusb library.
//! \~russian Класс PIUSB предоставляет функциональность для работы с USB-устройствами через библиотеку libusb.
class PIP_USB_EXPORT PIUSB: public PIIODevice {
PIIODEVICE(PIUSB, "usb");
public:
//! \~english Constructs USB device wrapper for vendor ID "vid" and product ID "pid".
//! \~russian Создает обертку USB-устройства для vendor ID "vid" и product ID "pid".
explicit PIUSB(ushort vid = 0, ushort pid = 0);
//! \~english Destroys the USB device wrapper.
//! \~russian Уничтожает обертку USB-устройства.
virtual ~PIUSB();
//! \~\ingroup USB
//! \~\brief
//! \~english Parsed USB endpoint descriptor.
//! \~russian Разобранный дескриптор USB endpoint.
struct PIP_USB_EXPORT Endpoint {
//! \~english Constructs endpoint descriptor and parses cached properties.
//! \~russian Создает дескриптор endpoint и разбирает кэшируемые свойства.
Endpoint(uchar a = 0, uchar at = 0, ushort mps = 0) {
address = a;
attributes = at;
max_packet_size = mps;
parse();
}
//! \~english Transfer direction encoded in endpoint address.
//! \~russian Направление передачи, закодированное в адресе endpoint.
enum Direction {
Write = 0 /** \~english Host-to-device endpoint \~russian Endpoint от хоста к устройству */,
Read = 1 /** \~english Device-to-host endpoint \~russian Endpoint от устройства к хосту */
};
//! \~english USB transfer type encoded in endpoint attributes.
//! \~russian Тип USB-передачи, закодированный в атрибутах endpoint.
enum TransferType {
Control = 0 /** \~english Control endpoint \~russian Control-endpoint */,
Isochronous = 1 /** \~english Isochronous endpoint \~russian Isochronous-endpoint */,
Bulk = 2 /** \~english Bulk endpoint \~russian Bulk-endpoint */,
Interrupt = 3 /** \~english Interrupt endpoint \~russian Interrupt-endpoint */
};
//! \~english Synchronisation mode for isochronous endpoints.
//! \~russian Режим синхронизации для isochronous-endpoint.
enum SynchronisationType {
NoSynchonisation = 0 /** \~english No synchronisation \~russian Без синхронизации */,
Asynchronous = 2 /** \~english Asynchronous synchronisation \~russian Асинхронная синхронизация */,
Adaptive = 1 /** \~english Adaptive synchronisation \~russian Адаптивная синхронизация */,
Synchronous = 3 /** \~english Synchronous synchronisation \~russian Синхронная синхронизация */
};
//! \~english Usage mode for isochronous endpoints.
//! \~russian Режим использования для isochronous-endpoint.
enum UsageType {
DataEndpoint = 0 /** \~english Data endpoint \~russian Endpoint данных */,
FeedbackEndpoint = 2 /** \~english Feedback endpoint \~russian Endpoint обратной связи */,
ExplicitFeedbackDataEndpoint =
1 /** \~english Explicit feedback data endpoint \~russian Endpoint данных с явной обратной связью */
};
//! \~english Parses direction and transfer information from \a address and \a attributes.
//! \~russian Разбирает направление и тип передачи из \a address и \a attributes.
void parse();
//! \~english Returns true if the endpoint is not selected.
//! \~russian Возвращает true, если endpoint не выбран.
bool isNull() const { return address == 0; }
//! \~english Raw USB endpoint address.
//! \~russian Сырой адрес USB endpoint.
uchar address;
//! \~english Raw USB endpoint attributes.
//! \~russian Сырые атрибуты USB endpoint.
uchar attributes;
//! \~english Maximum packet size in bytes.
//! \~russian Максимальный размер пакета в байтах.
ushort max_packet_size;
//! \~english Parsed transfer direction.
//! \~russian Разобранное направление передачи.
Direction direction;
//! \~english Parsed transfer type.
//! \~russian Разобранный тип передачи.
TransferType transfer_type;
//! \~english Parsed synchronisation type for isochronous transfers.
//! \~russian Разобранный тип синхронизации для isochronous-передач.
SynchronisationType synchronisation_type = NoSynchonisation;
//! \~english Parsed usage type for isochronous transfers.
//! \~russian Разобранный режим использования для isochronous-передач.
UsageType usage_type = DataEndpoint;
};
//! \~\ingroup USB
//! \~\brief
//! \~english USB interface description with its endpoints.
//! \~russian Описание USB-интерфейса и его endpoint.
struct PIP_USB_EXPORT Interface {
//! \~english Index inside the configuration descriptor.
//! \~russian Индекс внутри дескриптора конфигурации.
uchar index = 0;
//! \~english Value used to select this interface.
//! \~russian Значение, используемое для выбора этого интерфейса.
uchar value_to_select = 0;
//! \~english USB interface class code.
//! \~russian Код класса USB-интерфейса.
ushort class_code = 0;
//! \~english USB interface subclass code.
//! \~russian Код подкласса USB-интерфейса.
ushort subclass_code = 0;
//! \~english USB interface protocol code.
//! \~russian Код протокола USB-интерфейса.
ushort protocol_code = 0;
//! \~english Endpoints exposed by this interface.
//! \~russian Endpoint, доступные у этого интерфейса.
PIVector<PIUSB::Endpoint> endpoints;
};
//! \~\ingroup USB
//! \~\brief
//! \~english USB configuration description with available interfaces.
//! \~russian Описание USB-конфигурации с доступными интерфейсами.
struct PIP_USB_EXPORT Configuration {
//! \~english Index inside the device descriptor.
//! \~russian Индекс внутри дескриптора устройства.
uchar index = 0;
//! \~english Value used to select this configuration.
//! \~russian Значение, используемое для выбора этой конфигурации.
uchar value_to_select = 0;
//! \~english Raw USB configuration attributes.
//! \~russian Сырые атрибуты USB-конфигурации.
uchar attributes = 0;
//! \~english Maximum bus power in mA.
//! \~russian Максимальное потребление по шине в мА.
ushort max_power = 0;
//! \~english True if the device is self-powered in this configuration.
//! \~russian True, если устройство в этой конфигурации имеет собственное питание.
bool self_powered = false;
//! \~english True if remote wakeup is supported.
//! \~russian True, если поддерживается remote wakeup.
bool remote_wakeup = false;
//! \~english Interfaces available in this configuration.
//! \~russian Интерфейсы, доступные в этой конфигурации.
PIVector<PIUSB::Interface> interfaces;
};
//! \~\ingroup USB
//! \~\brief
//! \~english Top-level USB device descriptor collected during opening.
//! \~russian Верхнеуровневый USB-дескриптор, собранный при открытии.
struct PIP_USB_EXPORT Descriptor {
//! \~english USB specification version in BCD form.
//! \~russian Версия спецификации USB в BCD-форме.
ushort usb_spec_number = 0;
//! \~english Device class code.
//! \~russian Код класса устройства.
uchar device_class = 0;
//! \~english Device subclass code.
//! \~russian Код подкласса устройства.
uchar device_subclass = 0;
//! \~english Device protocol code.
//! \~russian Код протокола устройства.
uchar device_protocol = 0;
//! \~english Maximum packet size for endpoint zero.
//! \~russian Максимальный размер пакета для endpoint zero.
uchar max_packet_size = 0;
//! \~english Vendor identifier.
//! \~russian Идентификатор производителя.
ushort id_vendor = 0;
//! \~english Product identifier.
//! \~russian Идентификатор продукта.
ushort id_product = 0;
//! \~english Device release number in BCD form.
//! \~russian Номер релиза устройства в BCD-форме.
ushort id_device_release = 0;
//! \~english Index of manufacturer string descriptor.
//! \~russian Индекс строкового дескриптора производителя.
uchar index_manufacturer = 0;
//! \~english Index of product string descriptor.
//! \~russian Индекс строкового дескриптора продукта.
uchar index_product = 0;
//! \~english Index of serial number string descriptor.
//! \~russian Индекс строкового дескриптора серийного номера.
uchar index_serial = 0;
//! \~english Available device configurations.
//! \~russian Доступные конфигурации устройства.
PIVector<PIUSB::Configuration> configurations;
};
//! \~english Returns descriptor collected for the currently opened device.
//! \~russian Возвращает дескриптор, собранный для текущего открытого устройства.
const PIUSB::Descriptor & currentDescriptor() const { return desc_; }
//! \~english Returns the currently selected configuration description.
//! \~russian Возвращает описание текущей выбранной конфигурации.
const PIUSB::Configuration & currentConfiguration() const { return conf_; }
//! \~english Returns the currently selected interface description.
//! \~russian Возвращает описание текущего выбранного интерфейса.
const PIUSB::Interface & currentInterface() const { return iface_; }
//! \~english Returns current vendor ID filter.
//! \~russian Возвращает текущий фильтр vendor ID.
ushort vendorID() const { return vid_; }
//! \~english Returns current product ID filter.
//! \~russian Возвращает текущий фильтр product ID.
ushort productID() const { return pid_; }
//! \~english Returns ordinal number among devices with matching vendor and product IDs.
//! \~russian Возвращает порядковый номер среди устройств с теми же vendor ID и product ID.
int deviceNumber() const { return property("deviceNumber").toInt(); }
//! \~english Returns read timeout in milliseconds.
//! \~russian Возвращает таймаут чтения в миллисекундах.
int timeoutRead() const { return property("timeoutRead").toInt(); }
//! \~english Returns write timeout in milliseconds.
//! \~russian Возвращает таймаут записи в миллисекундах.
int timeoutWrite() const { return property("timeoutWrite").toInt(); }
//! \~english Returns endpoint used by \a read().
//! \~russian Возвращает endpoint, используемый методом \a read().
const PIUSB::Endpoint & endpointRead() const { return ep_read; }
//! \~english Returns endpoint used by \a write().
//! \~russian Возвращает endpoint, используемый методом \a write().
const PIUSB::Endpoint & endpointWrite() const { return ep_write; }
//! \~english Returns endpoints of the currently selected interface.
//! \~russian Возвращает endpoint текущего выбранного интерфейса.
const PIVector<PIUSB::Endpoint> & endpoints() const { return eps; }
//! \~english Returns only readable endpoints from \a endpoints().
//! \~russian Возвращает только endpoint для чтения из \a endpoints().
PIVector<PIUSB::Endpoint> endpointsRead();
//! \~english Returns only writable endpoints from \a endpoints().
//! \~russian Возвращает только endpoint для записи из \a endpoints().
PIVector<PIUSB::Endpoint> endpointsWrite();
//! \~english Returns endpoint with address "address", or null endpoint if it is absent.
//! \~russian Возвращает endpoint с адресом "address" или нулевой endpoint, если он отсутствует.
PIUSB::Endpoint getEndpointByAddress(uchar address);
//! \~english Sets vendor ID filter and updates device path.
//! \~russian Устанавливает фильтр vendor ID и обновляет путь устройства.
void setVendorID(ushort vid);
//! \~english Sets product ID filter and updates device path.
//! \~russian Устанавливает фильтр product ID и обновляет путь устройства.
void setProductID(ushort pid);
//! \~english Selects configuration by its public value and switches to its first interface.
//! \~russian Выбирает конфигурацию по её публичному значению и переключается на её первый интерфейс.
bool setConfiguration(uchar value);
//! \~english Selects interface by its public value and refreshes active endpoints.
//! \~russian Выбирает интерфейс по его публичному значению и обновляет активные endpoint.
bool setInterface(uchar value);
//! \~english Sets endpoint used by \a read().
//! \~russian Устанавливает endpoint, используемый методом \a read().
void setEndpointRead(const PIUSB::Endpoint & ep) { ep_read = ep; }
//! \~english Sets endpoint used by \a write().
//! \~russian Устанавливает endpoint, используемый методом \a write().
void setEndpointWrite(const PIUSB::Endpoint & ep) { ep_write = ep; }
//! \~english Selects which matching device instance should be opened.
//! \~russian Выбирает, какой экземпляр среди совпадающих устройств должен быть открыт.
void setDeviceNumber(int dn) { setProperty("deviceNumber", dn); }
//! \~english Sets read timeout in milliseconds.
//! \~russian Устанавливает таймаут чтения в миллисекундах.
void setTimeoutRead(int t) { setProperty("timeoutRead", t); }
//! \~english Sets write timeout in milliseconds.
//! \~russian Устанавливает таймаут записи в миллисекундах.
void setTimeoutWrite(int t) { setProperty("timeoutWrite", t); }
//! \~english Reserved control-transfer write helper.
//! \~russian Зарезервированный helper для записи через control-transfer.
int controlWrite(const void * data, int max_size);
//! \~english Resets currently selected read and write endpoints.
//! \~russian Сбрасывает текущие выбранные endpoint чтения и записи.
virtual void flush() override;
protected:
bool configureDevice(const void * e_main, const void * e_parent = 0) override;
PIString constructFullPathDevice() const override;
void configureFromFullPathDevice(const PIString & full_path) override;
ssize_t readDevice(void * read_to, ssize_t max_size) override;
ssize_t writeDevice(const void * data, ssize_t max_size) override;
bool openDevice() override;
bool closeDevice() override;
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
PIVector<PIUSB::Endpoint> eps;
ushort vid_, pid_;
int intefrace_, timeout_r, timeout_w;
int interface_claimed;
PIUSB::Endpoint ep_read, ep_write;
Descriptor desc_;
Configuration conf_;
Interface iface_;
usb_dev_handle * hdev;
};
//! \relatesalso PICout
//! \~english Writes endpoint description to \a PICout.
//! \~russian Выводит описание endpoint в \a PICout.
PIP_USB_EXPORT PICout operator<<(PICout s, const PIUSB::Endpoint & v);
#endif