hid: add support of android devices

This commit is contained in:
DH 2025-03-03 21:59:08 +03:00 committed by Megamouse
parent d766baef12
commit 8100779512
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(); 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) 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) PadHandlerBase::connection ds3_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{ {
ds3_device* dev = static_cast<ds3_device*>(device.get()); 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; return connection::disconnected;
if (dev->hidDevice == nullptr) 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())) if (hid_device* hid_dev = hid_open_path(dev->path.c_str()))
#endif
{ {
if (hid_set_nonblocking(hid_dev, 1) == -1) if (hid_set_nonblocking(hid_dev, 1) == -1)
{ {

View file

@ -145,7 +145,7 @@ public:
private: private:
ds3_pad_handler::DataStatus get_data(ds3_device* ds3dev) override; ds3_pad_handler::DataStatus get_data(ds3_device* ds3dev) override;
int send_output_report(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_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; 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; 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) 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) PadHandlerBase::connection ds4_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{ {
DS4Device* dev = static_cast<DS4Device*>(device.get()); DS4Device* dev = static_cast<DS4Device*>(device.get());
if (!dev || dev->path.empty()) if (!dev || dev->path == hid_enumerated_device_default)
return connection::disconnected; return connection::disconnected;
if (dev->hidDevice == nullptr) if (dev->hidDevice == nullptr)
{ {
// try to reconnect // 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())) if (hid_device* hid_dev = hid_open_path(dev->path.c_str()))
#endif
{ {
if (hid_set_nonblocking(hid_dev, 1) == -1) 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 // Copies data into padData if status is NewData, otherwise buffer is untouched
DataStatus get_data(DS4Device* ds4Device) override; DataStatus get_data(DS4Device* ds4Device) override;
int send_output_report(DS4Device* device) 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_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; 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; 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) 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) PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{ {
DualSenseDevice* dev = static_cast<DualSenseDevice*>(device.get()); DualSenseDevice* dev = static_cast<DualSenseDevice*>(device.get());
if (!dev || dev->path.empty()) if (!dev || dev->path == hid_enumerated_device_default)
return connection::disconnected; return connection::disconnected;
if (dev->hidDevice == nullptr) if (dev->hidDevice == nullptr)
{ {
// try to reconnect // 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())) if (hid_device* hid_dev = hid_open_path(dev->path.c_str()))
#endif
{ {
if (hid_set_nonblocking(hid_dev, 1) == -1) if (hid_set_nonblocking(hid_dev, 1) == -1)
{ {

View file

@ -245,7 +245,7 @@ private:
bool get_calibration_data(DualSenseDevice* dev) const; bool get_calibration_data(DualSenseDevice* dev) const;
DataStatus get_data(DualSenseDevice* device) override; 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; int send_output_report(DualSenseDevice* device) override;
bool get_is_left_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode) 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"); 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 struct hid_instance
{ {
public: public:
@ -56,9 +61,9 @@ public:
hid_log.notice("Initializing HIDAPI ..."); 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; return false;
} }
@ -179,9 +184,18 @@ template <class Device>
void hid_pad_handler<Device>::enumerate_devices() void hid_pad_handler<Device>::enumerate_devices()
{ {
Timer timer; Timer timer;
std::set<std::string> device_paths; std::set<hid_enumerated_device_type> device_paths;
std::map<std::string, std::wstring> serials; 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) for (const auto& [vid, pid] : m_ids)
{ {
hid_device_info* dev_info = hid_enumerate(vid, pid); hid_device_info* dev_info = hid_enumerate(vid, pid);
@ -209,6 +223,7 @@ void hid_pad_handler<Device>::enumerate_devices()
} }
hid_free_enumeration(head); hid_free_enumeration(head);
} }
#endif
hid_log.notice("%s enumeration found %d devices (%f ms)", m_type, device_paths.size(), timer.GetElapsedTimeInMilliSec()); hid_log.notice("%s enumeration found %d devices (%f ms)", m_type, device_paths.size(), timer.GetElapsedTimeInMilliSec());
std::lock_guard lock(m_enumeration_mutex); 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 // Scrap devices that are not in the new list
for (auto& controller : m_controllers) 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(); controller.second->close();
cfg_pad* config = controller.second->config; cfg_pad* config = controller.second->config;
@ -284,7 +299,11 @@ void hid_pad_handler<Device>::update_devices()
} }
#endif #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)) if (const hid_device_info* info = hid_get_device_info(dev))
{ {

View file

@ -6,8 +6,24 @@
#include "hidapi.h" #include "hidapi.h"
#ifdef ANDROID
#include "hidapi_libusb.h"
#endif
#include <mutex> #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 struct CalibData
{ {
s16 bias = 0; s16 bias = 0;
@ -38,7 +54,7 @@ public:
#ifdef _WIN32 #ifdef _WIN32
hid_device* bt_device{nullptr}; // Used in ps move handler hid_device* bt_device{nullptr}; // Used in ps move handler
#endif #endif
std::string path; hid_enumerated_device_type path = hid_enumerated_device_default;
u8 led_delay_on{0}; u8 led_delay_on{0};
u8 led_delay_off{0}; u8 led_delay_off{0};
u8 battery_level{0}; u8 battery_level{0};
@ -78,9 +94,9 @@ protected:
// pseudo 'controller id' to keep track of unique controllers // pseudo 'controller id' to keep track of unique controllers
std::map<std::string, std::shared_ptr<Device>> m_controllers; std::map<std::string, std::shared_ptr<Device>> m_controllers;
std::set<std::string> m_last_enumerated_devices; std::set<hid_enumerated_device_type> m_last_enumerated_devices;
std::set<std::string> m_new_enumerated_devices; std::set<hid_enumerated_device_type> m_new_enumerated_devices;
std::map<std::string, std::wstring> m_enumerated_serials; std::map<hid_enumerated_device_type, std::wstring> m_enumerated_serials;
std::mutex m_enumeration_mutex; std::mutex m_enumeration_mutex;
std::unique_ptr<named_thread<std::function<void()>>> m_enumeration_thread; std::unique_ptr<named_thread<std::function<void()>>> m_enumeration_thread;
@ -88,7 +104,7 @@ protected:
void update_devices(); void update_devices();
std::shared_ptr<Device> get_hid_device(const std::string& padId); 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 int send_output_report(Device* device) = 0;
virtual DataStatus get_data(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 #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 #ifndef _WIN32
if (!hidDevice) 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) 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()); 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; return connection::disconnected;
if (move_device->hidDevice == nullptr) if (move_device->hidDevice == nullptr)
@ -433,8 +433,12 @@ PadHandlerBase::connection ps_move_handler::update_connection(const std::shared_
{ {
move_device->hidDevice = dev; move_device->hidDevice = dev;
} }
#else
#ifdef ANDROID
if (hid_device* dev = hid_libusb_wrap_sys_device(move_device->path, -1))
#else #else
if (hid_device* dev = hid_open_path(move_device->path.c_str())) if (hid_device* dev = hid_open_path(move_device->path.c_str()))
#endif
{ {
if (hid_set_nonblocking(dev, 1) == -1) if (hid_set_nonblocking(dev, 1) == -1)
{ {

View file

@ -189,7 +189,7 @@ private:
#endif #endif
DataStatus get_data(ps_move_device* device) override; 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; int send_output_report(ps_move_device* device) override;
bool get_is_left_trigger(const std::shared_ptr<PadDevice>& device, u64 keyCode) 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(); 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) 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) PadHandlerBase::connection skateboard_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{ {
skateboard_device* dev = static_cast<skateboard_device*>(device.get()); 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; return connection::disconnected;
if (dev->hidDevice == nullptr) if (dev->hidDevice == nullptr)
{ {
// try to reconnect // 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())) if (hid_device* hid_dev = hid_open_path(dev->path.c_str()))
#endif
{ {
if (hid_set_nonblocking(hid_dev, 1) == -1) if (hid_set_nonblocking(hid_dev, 1) == -1)
{ {

View file

@ -179,7 +179,7 @@ public:
private: private:
DataStatus get_data(skateboard_device* device) override; 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; int send_output_report(skateboard_device* device) override;
PadHandlerBase::connection update_connection(const std::shared_ptr<PadDevice>& device) override; PadHandlerBase::connection update_connection(const std::shared_ptr<PadDevice>& device) override;