From f66b167da9a35be83ad32a16b0a8bc77f52b8e86 Mon Sep 17 00:00:00 2001 From: Benedek Kupper Date: Sun, 26 May 2024 23:32:57 +0200 Subject: [PATCH] hid-application: add a helper class that can combine multiple applications behind a single one This is motivated by Android's BLE stack, that (unlike other major OS-es) deviates from the standard by only accepting a single HOGP service. --- c2usb/hid/application.hpp | 61 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/c2usb/hid/application.hpp b/c2usb/hid/application.hpp index 75cdcb0..4e89168 100644 --- a/c2usb/hid/application.hpp +++ b/c2usb/hid/application.hpp @@ -15,6 +15,7 @@ #include #include +#include "reference_array_view.hpp" #include "usb/base.hpp" namespace hid @@ -193,6 +194,66 @@ class application : public polymorphic private: std::atomic transport_{}; + friend class multi_application; +}; + +/// @brief The multi_application is a helper to combine multiple TLC applications into a single HID +/// instance. If boot protocol is supported, its application must be the first parameter. +class multi_application : public application +{ + protected: + multi_application(const report_protocol& prot, reference_array_view apps) + : application(prot), apps_(apps) + {} + + private: + template + void dispatch(T (application::*method)(Targs1...), Targs2&&... args) const + { + if (get_protocol() == protocol::BOOT) + { + (apps_[0]->*method)(std::forward(args)...); + } + else + { + for (auto* app : apps_) + { + (app->*method)(std::forward(args)...); + } + } + } + void start(protocol prot) override + { + transport_copy_ = transport_.load(); + if (prot == protocol::BOOT) + { + apps_[0]->setup(transport_copy_, prot); + } + else + { + for (auto* app : apps_) + { + app->setup(transport_copy_, prot); + } + } + } + void stop() override { dispatch(&application::teardown, transport_copy_); } + void set_report(report::type type, const std::span& data) override + { + dispatch(&application::set_report, type, data); + } + void get_report(report::selector select, const std::span& buffer) override + { + dispatch(&application::get_report, select, buffer); + } + void in_report_sent(const std::span& data) override + { + dispatch(&application::in_report_sent, data); + } + protocol get_protocol() const override { return apps_[0]->get_protocol(); } + + const reference_array_view apps_; + transport* transport_copy_{}; }; /// @brief Helper class to manage FEATURE and OUTPUT buffers.