hid: add support of android devices

This commit is contained in:
DH 2025-03-03 21:59:08 +03:00 committed by Megamouse
parent 58b914c95a
commit 853310e4d5
12 changed files with 81 additions and 26 deletions

View file

@ -218,7 +218,7 @@ void ds3_pad_handler::init_config(cfg_pad* cfg)
cfg->from_default();
}
void ds3_pad_handler::check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial)
void ds3_pad_handler::check_add_device(hid_device* hidDevice, hid_enumerated_device_view path, std::wstring_view wide_serial)
{
if (!hidDevice)
{
@ -508,12 +508,16 @@ bool ds3_pad_handler::get_is_right_stick(const std::shared_ptr<PadDevice>& /*dev
PadHandlerBase::connection ds3_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{
ds3_device* dev = static_cast<ds3_device*>(device.get());
if (!dev || dev->path.empty())
if (!dev || dev->path == hid_enumerated_device_default)
return connection::disconnected;
if (dev->hidDevice == nullptr)
{
#ifdef ANDROID
if (hid_device* hid_dev = hid_libusb_wrap_sys_device(dev->path, -1))
#else
if (hid_device* hid_dev = hid_open_path(dev->path.c_str()))
#endif
{
if (hid_set_nonblocking(hid_dev, 1) == -1)
{

View file

@ -145,7 +145,7 @@ public:
private:
ds3_pad_handler::DataStatus get_data(ds3_device* ds3dev) override;
int send_output_report(ds3_device* ds3dev) override;
void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view serial) override;
void check_add_device(hid_device* hidDevice, hid_enumerated_device_view path, std::wstring_view serial) override;
bool get_is_left_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode) override;
bool get_is_right_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode) override;

View file

@ -556,7 +556,7 @@ bool ds4_pad_handler::GetCalibrationData(DS4Device* ds4Dev) const
return true;
}
void ds4_pad_handler::check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial)
void ds4_pad_handler::check_add_device(hid_device* hidDevice, hid_enumerated_device_view path, std::wstring_view wide_serial)
{
if (!hidDevice)
{
@ -831,13 +831,17 @@ bool ds4_pad_handler::get_is_touch_pad_motion(const std::shared_ptr<PadDevice>&
PadHandlerBase::connection ds4_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{
DS4Device* dev = static_cast<DS4Device*>(device.get());
if (!dev || dev->path.empty())
if (!dev || dev->path == hid_enumerated_device_default)
return connection::disconnected;
if (dev->hidDevice == nullptr)
{
// try to reconnect
#ifdef ANDROID
if (hid_device* hid_dev = hid_libusb_wrap_sys_device(dev->path, -1))
#else
if (hid_device* hid_dev = hid_open_path(dev->path.c_str()))
#endif
{
if (hid_set_nonblocking(hid_dev, 1) == -1)
{

View file

@ -184,7 +184,7 @@ private:
// Copies data into padData if status is NewData, otherwise buffer is untouched
DataStatus get_data(DS4Device* ds4Device) override;
int send_output_report(DS4Device* device) override;
void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view serial) override;
void check_add_device(hid_device* hidDevice, hid_enumerated_device_view path, std::wstring_view serial) override;
bool get_is_left_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode) override;
bool get_is_right_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode) override;

View file

@ -99,7 +99,7 @@ dualsense_pad_handler::dualsense_pad_handler()
m_thumb_threshold = thumb_max / 2;
}
void dualsense_pad_handler::check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial)
void dualsense_pad_handler::check_add_device(hid_device* hidDevice, hid_enumerated_device_view path, std::wstring_view wide_serial)
{
if (!hidDevice)
{
@ -562,13 +562,17 @@ bool dualsense_pad_handler::get_is_touch_pad_motion(const std::shared_ptr<PadDev
PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{
DualSenseDevice* dev = static_cast<DualSenseDevice*>(device.get());
if (!dev || dev->path.empty())
if (!dev || dev->path == hid_enumerated_device_default)
return connection::disconnected;
if (dev->hidDevice == nullptr)
{
// try to reconnect
#ifdef ANDROID
if (hid_device* hid_dev = hid_libusb_wrap_sys_device(dev->path, -1))
#else
if (hid_device* hid_dev = hid_open_path(dev->path.c_str()))
#endif
{
if (hid_set_nonblocking(hid_dev, 1) == -1)
{

View file

@ -245,7 +245,7 @@ private:
bool get_calibration_data(DualSenseDevice* dev) const;
DataStatus get_data(DualSenseDevice* device) override;
void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial) override;
void check_add_device(hid_device* hidDevice, hid_enumerated_device_view path, std::wstring_view wide_serial) override;
int send_output_report(DualSenseDevice* device) override;
bool get_is_left_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode) override;

View file

@ -18,6 +18,11 @@
LOG_CHANNEL(hid_log, "HID");
#ifdef ANDROID
std::vector<int> g_android_usb_devices;
std::mutex g_android_usb_devices_mutex;
#endif
struct hid_instance
{
public:
@ -56,9 +61,9 @@ public:
hid_log.notice("Initializing HIDAPI ...");
if (hid_init() != 0)
if (int errorCode = hid_init(); errorCode != 0)
{
hid_log.fatal("hid_init error");
hid_log.fatal("hid_init error %d", errorCode);
return false;
}
@ -179,9 +184,18 @@ template <class Device>
void hid_pad_handler<Device>::enumerate_devices()
{
Timer timer;
std::set<std::string> device_paths;
std::map<std::string, std::wstring> serials;
std::set<hid_enumerated_device_type> device_paths;
std::map<hid_enumerated_device_type, std::wstring> serials;
#ifdef ANDROID
{
std::lock_guard lock(g_android_usb_devices_mutex);
for (auto device : g_android_usb_devices)
{
device_paths.insert(device);
}
}
#else
for (const auto& [vid, pid] : m_ids)
{
hid_device_info* dev_info = hid_enumerate(vid, pid);
@ -209,6 +223,7 @@ void hid_pad_handler<Device>::enumerate_devices()
}
hid_free_enumeration(head);
}
#endif
hid_log.notice("%s enumeration found %d devices (%f ms)", m_type, device_paths.size(), timer.GetElapsedTimeInMilliSec());
std::lock_guard lock(m_enumeration_mutex);
@ -254,7 +269,7 @@ void hid_pad_handler<Device>::update_devices()
// Scrap devices that are not in the new list
for (auto& controller : m_controllers)
{
if (controller.second && !controller.second->path.empty() && !m_new_enumerated_devices.contains(controller.second->path))
if (controller.second && controller.second->path != hid_enumerated_device_default && !m_new_enumerated_devices.contains(controller.second->path))
{
controller.second->close();
cfg_pad* config = controller.second->config;
@ -284,7 +299,11 @@ void hid_pad_handler<Device>::update_devices()
}
#endif
if (hid_device* dev = hid_open_path(path.c_str()))
#ifdef ANDROID
if (hid_device* dev = hid_libusb_wrap_sys_device(path, -1))
#else
if (hid_device* dev = hid_open_path(path))
#endif
{
if (const hid_device_info* info = hid_get_device_info(dev))
{

View file

@ -6,8 +6,24 @@
#include "hidapi.h"
#ifdef ANDROID
#include "hidapi_libusb.h"
#endif
#include <mutex>
#ifdef ANDROID
using hid_enumerated_device_type = int;
using hid_enumerated_device_view = int;
inline constexpr auto hid_enumerated_device_default = -1;
extern std::vector<int> g_android_usb_devices;
extern std::mutex g_android_usb_devices_mutex;
#else
using hid_enumerated_device_type = std::string;
using hid_enumerated_device_view = std::string_view;
inline constexpr auto hid_enumerated_device_default = std::string();
#endif
struct CalibData
{
s16 bias = 0;
@ -38,7 +54,7 @@ public:
#ifdef _WIN32
hid_device* bt_device{nullptr}; // Used in ps move handler
#endif
std::string path;
hid_enumerated_device_type path = hid_enumerated_device_default;
u8 led_delay_on{0};
u8 led_delay_off{0};
u8 battery_level{0};
@ -78,9 +94,9 @@ protected:
// pseudo 'controller id' to keep track of unique controllers
std::map<std::string, std::shared_ptr<Device>> m_controllers;
std::set<std::string> m_last_enumerated_devices;
std::set<std::string> m_new_enumerated_devices;
std::map<std::string, std::wstring> m_enumerated_serials;
std::set<hid_enumerated_device_type> m_last_enumerated_devices;
std::set<hid_enumerated_device_type> m_new_enumerated_devices;
std::map<hid_enumerated_device_type, std::wstring> m_enumerated_serials;
std::mutex m_enumeration_mutex;
std::unique_ptr<named_thread<std::function<void()>>> m_enumeration_thread;
@ -88,7 +104,7 @@ protected:
void update_devices();
std::shared_ptr<Device> get_hid_device(const std::string& padId);
virtual void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view serial) = 0;
virtual void check_add_device(hid_device* hidDevice, hid_enumerated_device_view path, std::wstring_view serial) = 0;
virtual int send_output_report(Device* device) = 0;
virtual DataStatus get_data(Device* device) = 0;

View file

@ -265,7 +265,7 @@ hid_device* ps_move_handler::connect_move_device(ps_move_device* device, std::st
}
#endif
void ps_move_handler::check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial)
void ps_move_handler::check_add_device(hid_device* hidDevice, hid_enumerated_device_view path, std::wstring_view wide_serial)
{
#ifndef _WIN32
if (!hidDevice)
@ -422,7 +422,7 @@ ps_move_handler::DataStatus ps_move_handler::get_data(ps_move_device* device)
PadHandlerBase::connection ps_move_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{
ps_move_device* move_device = static_cast<ps_move_device*>(device.get());
if (!move_device || move_device->path.empty())
if (!move_device || move_device->path == hid_enumerated_device_default)
return connection::disconnected;
if (move_device->hidDevice == nullptr)
@ -433,8 +433,12 @@ PadHandlerBase::connection ps_move_handler::update_connection(const std::shared_
{
move_device->hidDevice = dev;
}
#else
#ifdef ANDROID
if (hid_device* dev = hid_libusb_wrap_sys_device(move_device->path, -1))
#else
if (hid_device* dev = hid_open_path(move_device->path.c_str()))
#endif
{
if (hid_set_nonblocking(dev, 1) == -1)
{

View file

@ -189,7 +189,7 @@ private:
#endif
DataStatus get_data(ps_move_device* device) override;
void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial) override;
void check_add_device(hid_device* hidDevice, hid_enumerated_device_view path, std::wstring_view wide_serial) override;
int send_output_report(ps_move_device* device) override;
bool get_is_left_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode) override;

View file

@ -149,7 +149,7 @@ void skateboard_pad_handler::init_config(cfg_pad* cfg)
cfg->from_default();
}
void skateboard_pad_handler::check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial)
void skateboard_pad_handler::check_add_device(hid_device* hidDevice, hid_enumerated_device_view path, std::wstring_view wide_serial)
{
if (!hidDevice)
{
@ -233,13 +233,17 @@ skateboard_pad_handler::DataStatus skateboard_pad_handler::get_data(skateboard_d
PadHandlerBase::connection skateboard_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{
skateboard_device* dev = static_cast<skateboard_device*>(device.get());
if (!dev || dev->path.empty())
if (!dev || dev->path == hid_enumerated_device_default)
return connection::disconnected;
if (dev->hidDevice == nullptr)
{
// try to reconnect
#ifdef ANDROID
if (hid_device* hid_dev = hid_libusb_wrap_sys_device(dev->path, -1))
#else
if (hid_device* hid_dev = hid_open_path(dev->path.c_str()))
#endif
{
if (hid_set_nonblocking(hid_dev, 1) == -1)
{

View file

@ -179,7 +179,7 @@ public:
private:
DataStatus get_data(skateboard_device* device) override;
void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial) override;
void check_add_device(hid_device* hidDevice, hid_enumerated_device_view path, std::wstring_view wide_serial) override;
int send_output_report(skateboard_device* device) override;
PadHandlerBase::connection update_connection(const std::shared_ptr<PadDevice>& device) override;