//! \~\file pihidevice.h
//! \~\ingroup System
//! \~\brief
//! \~english HID device
//! \~russian HID устройство
/*
PIP - Platform Independent Primitives
HID device
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 .
*/
#ifndef PIHIDEVICE_H
#define PIHIDEVICE_H
#include "pithread.h"
//! \~\ingroup System
//! \~\brief
//! \~english Information about a discovered HID device.
//! \~russian Информация об обнаруженном HID-устройстве.
struct PIP_EXPORT PIHIDeviceInfo {
friend class PIHIDevice;
//! \~\ingroup System
//! \~\brief
//! \~english Common information for HID controls addressed by index.
//! \~russian Общая информация об HID-элементах управления, адресуемых по индексу.
struct PIP_EXPORT ValueInfoBase {
//! \~english Returns \b true when this control description is initialized.
//! \~russian Возвращает \b true, если описание элемента управления инициализировано.
bool isValid() const { return index >= 0; }
//! \~english Sequential index in the corresponding public vector.
//! \~russian Порядковый индекс в соответствующем публичном векторе.
int index = -1;
//! \~english Platform data index used in input reports.
//! \~russian Платформенный индекс данных, используемый во входных отчетах.
int data_index = -1;
};
//! \~\ingroup System
//! \~\brief
//! \~english Description of a HID axis.
//! \~russian Описание HID-оси.
struct PIP_EXPORT AxisInfo: public ValueInfoBase {
//! \~english Axis resolution in bits when the platform reports it.
//! \~russian Разрешение оси в битах, если платформа его сообщает.
int bits = 0;
//! \~english Minimal raw axis value.
//! \~russian Минимальное сырое значение оси.
int min = 0;
//! \~english Maximal raw axis value.
//! \~russian Максимальное сырое значение оси.
int max = 1;
//! \~english Marks relative axes such as wheels or deltas.
//! \~russian Отмечает относительные оси, например колесо или дельты.
bool is_relative = false;
};
//! \~\ingroup System
//! \~\brief
//! \~english Description of a HID button.
//! \~russian Описание HID-кнопки.
struct PIP_EXPORT ButtonInfo: public ValueInfoBase {
//! \~english Platform button code when it is available.
//! \~russian Платформенный код кнопки, если он доступен.
int code = 0;
};
//! \~english Device path that can be passed to \a PIHIDevice::open().
//! \~russian Путь к устройству, который можно передать в \a PIHIDevice::open().
PIString path;
//! \~english Manufacturer name.
//! \~russian Имя производителя.
PIString manufacturer;
//! \~english Product name.
//! \~russian Имя продукта.
PIString product;
//! \~english Device serial number when available.
//! \~russian Серийный номер устройства, если доступен.
PIString serial;
//! \~english Device version string.
//! \~russian Строка версии устройства.
PIString version;
//! \~english USB vendor identifier.
//! \~russian Идентификатор производителя USB.
PIString VID;
//! \~english USB product identifier.
//! \~russian Идентификатор продукта USB.
PIString PID;
//! \~english All discovered axes in report order.
//! \~russian Все обнаруженные оси в порядке отчетов.
PIVector axes;
//! \~english All discovered buttons.
//! \~russian Все обнаруженные кнопки.
PIVector buttons;
//! \~english Returns \b true when this descriptor does not point to a device.
//! \~russian Возвращает \b true, если этот дескриптор не указывает на устройство.
bool isNull() const { return path.isEmpty(); }
//! \~english Returns \b true when this descriptor points to a device.
//! \~russian Возвращает \b true, если этот дескриптор указывает на устройство.
bool isNotNull() const { return !isNull(); }
//! \~english Checks whether product name or path contains \a str ignoring case.
//! \~russian Проверяет, содержит ли имя продукта или путь строку \a str без учета регистра.
bool match(const PIString & str) const;
//! \~english Returns total number of discovered axes.
//! \~russian Возвращает общее число обнаруженных осей.
int axesCount() const { return axes.size_s(); }
//! \~english Returns number of absolute axes.
//! \~russian Возвращает число абсолютных осей.
int axesAbsoluteCount() const;
//! \~english Returns number of relative axes.
//! \~russian Возвращает число относительных осей.
int axesRelativeCount() const;
//! \~english Returns total number of discovered buttons.
//! \~russian Возвращает общее число обнаруженных кнопок.
int buttonsCount() const { return buttons.size_s(); }
private:
void prepare();
PIMap axis_by_dataindex;
PIMap button_by_dataindex;
int input_report_size = 0;
int output_report_size = 0;
int feature_report_size = 0;
};
//! \relatesalso PIHIDeviceInfo
//! \~english Prints short HID device information to \a PICout.
//! \~russian Выводит краткую информацию об HID-устройстве в \a PICout.
PIP_EXPORT PICout operator<<(PICout s, const PIHIDeviceInfo & v);
//! \~\ingroup System
//! \~\brief
//! \~english Provides access to HID (Human Interface Device) devices such as game controllers, joysticks, and other input devices.
//! \~russian Предоставляет доступ к HID (Human Interface Device) устройствам, таким как геймконтроллеры, джойстики и другие устройства
//! ввода.
class PIP_EXPORT PIHIDevice: public PIThread {
PIOBJECT_SUBCLASS(PIHIDevice, PIThread)
public:
//! \~english Stops polling and closes the device.
//! \~russian Останавливает опрос и закрывает устройство.
~PIHIDevice();
//! \~\ingroup System
//! \~\brief
//! \~english Input event produced by %PIHIDevice.
//! \~russian Событие ввода, создаваемое %PIHIDevice.
struct PIP_EXPORT Event {
//! \~english Kind of HID event.
//! \~russian Вид HID-события.
enum Type {
tNone /** \~english Empty event \~russian Пустое событие */,
tButton /** \~english Button state change \~russian Изменение состояния кнопки */,
tAxisMove /** \~english Axis value change or relative axis delta \~russian Изменение значения оси или дельта относительной оси
*/
,
};
//! \~english Event kind.
//! \~russian Вид события.
Type type = tNone;
//! \~english Axis description for axis events.
//! \~russian Описание оси для событий оси.
PIHIDeviceInfo::AxisInfo axis;
//! \~english Button description for button events.
//! \~russian Описание кнопки для событий кнопки.
PIHIDeviceInfo::ButtonInfo button;
//! \~english Normalized axis value, relative delta, or button state.
//! \~russian Нормализованное значение оси, относительная дельта или состояние кнопки.
float value = 0.;
};
//! \~english Returns \b true when the device handle is open.
//! \~russian Возвращает \b true, если дескриптор устройства открыт.
bool isOpened() const;
//! \~english Opens the device described by \a device and stores it as current.
//! \~russian Открывает устройство, описанное в \a device, и сохраняет его как текущее.
bool open(const PIHIDeviceInfo & device);
//! \~english Reopens the device stored by the last successful \a open().
//! \~russian Повторно открывает устройство, сохраненное последним успешным вызовом \a open().
bool open();
//! \~english Stops reading and releases the current device handle.
//! \~russian Останавливает чтение и освобождает дескриптор текущего устройства.
void close();
//! \~english Starts polling the opened device for input changes.
//! \~russian Запускает опрос открытого устройства на изменения ввода.
void start();
//! \~english Stops device polling and waits for the thread to finish.
//! \~russian Останавливает опрос устройства и ожидает завершения потока.
void stop();
//! \~english Sets dead zone for absolute axes in normalized range.
//! \~russian Устанавливает мертвую зону для абсолютных осей в нормализованном диапазоне.
void setDeadZone(float v) { dead_zone = v; }
//! \~english Returns current dead zone for absolute axes.
//! \~russian Возвращает текущую мертвую зону для абсолютных осей.
float deadZone() const { return dead_zone; }
//! \events
//! \{
//! \fn void event(PIHIDevice::Event e)
//! \brief
//! \~english Raised when a button changes state or an axis value changes.
//! \~russian Генерируется при изменении состояния кнопки или значения оси.
EVENT1(event, PIHIDevice::Event, e);
//! \}
//! \~english Enumerates available HID devices. When \a try_open is enabled, inaccessible devices are skipped.
//! \~russian Перечисляет доступные HID-устройства. Если включен \a try_open, недоступные устройства пропускаются.
static PIVector allDevices(bool try_open = true);
//! \~english Returns the first device whose path or product matches \a name.
//! \~russian Возвращает первое устройство, у которого путь или имя продукта совпадает с \a name.
static PIHIDeviceInfo findDevice(const PIString & name);
private:
void run() override;
double procDeadZone(double in);
PRIVATE_DECLARATION(PIP_EXPORT)
PIHIDeviceInfo di;
PIMap prev_axes, cur_axes;
PIMap prev_buttons, cur_buttons;
float dead_zone = 0.f;
};
#endif