blob: c54781d698a6539fe3502d0338a6924c44783141 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_UI_INPUT_DRIVERS_HIDCTL_HIDCTL_H_
#define SRC_UI_INPUT_DRIVERS_HIDCTL_HIDCTL_H_
#include <fidl/fuchsia.hardware.hidbus/cpp/wire.h>
#include <fidl/fuchsia.hardware.hidctl/cpp/wire.h>
#include <lib/async/cpp/wait.h>
#include <lib/component/outgoing/cpp/outgoing_directory.h>
#include <lib/ddk/device.h>
#include <lib/zx/socket.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
#include <optional>
#include <ddktl/device.h>
#include <ddktl/protocol/empty-protocol.h>
#include <fbl/array.h>
#include <fbl/mutex.h>
namespace hidctl {
class HidCtl;
using DeviceType = ddk::Device<HidCtl, ddk::Messageable<fuchsia_hardware_hidctl::Device>::Mixin>;
class HidCtl : public DeviceType {
public:
HidCtl(zx_device_t* device);
static zx_status_t Create(void* ctx, zx_device_t* parent);
void DdkRelease();
void MakeHidDevice(MakeHidDeviceRequestView request, MakeHidDeviceCompleter::Sync& completer);
};
class HidDevice : public ddk::Device<HidDevice, ddk::Initializable, ddk::Unbindable>,
public ddk::EmptyProtocol<ZX_PROTOCOL_HIDBUS>,
public fidl::WireServer<fuchsia_hardware_hidbus::Hidbus> {
public:
HidDevice(zx_device_t* device, const fuchsia_hardware_hidctl::wire::HidCtlConfig& config,
fbl::Array<const uint8_t> report_desc, zx::socket data);
void DdkRelease();
void DdkInit(ddk::InitTxn txn);
void DdkUnbind(ddk::UnbindTxn txn);
zx::result<fidl::ClientEnd<fuchsia_io::Directory>> ServeOutgoing();
// fidl::WireServer<fuchsia_hardware_hidbus::Hidbus>:
void Query(QueryCompleter::Sync& completer) override;
void Start(StartCompleter::Sync& completer) override;
void Stop(StopCompleter::Sync& completer) override;
void GetDescriptor(fuchsia_hardware_hidbus::wire::HidbusGetDescriptorRequest* request,
GetDescriptorCompleter::Sync& completer) override;
void SetDescriptor(fuchsia_hardware_hidbus::wire::HidbusSetDescriptorRequest* request,
SetDescriptorCompleter::Sync& completer) override;
void GetReport(fuchsia_hardware_hidbus::wire::HidbusGetReportRequest* request,
GetReportCompleter::Sync& completer) override;
void SetReport(fuchsia_hardware_hidbus::wire::HidbusSetReportRequest* request,
SetReportCompleter::Sync& completer) override;
void GetIdle(fuchsia_hardware_hidbus::wire::HidbusGetIdleRequest* request,
GetIdleCompleter::Sync& completer) override;
void SetIdle(fuchsia_hardware_hidbus::wire::HidbusSetIdleRequest* request,
SetIdleCompleter::Sync& completer) override;
void GetProtocol(GetProtocolCompleter::Sync& completer) override;
void SetProtocol(fuchsia_hardware_hidbus::wire::HidbusSetProtocolRequest* request,
SetProtocolCompleter::Sync& completer) override;
private:
zx_status_t Recv(uint8_t* buffer, uint32_t capacity);
void Stop();
component::OutgoingDirectory outgoing_;
std::optional<fidl::ServerBinding<fuchsia_hardware_hidbus::Hidbus>> binding_;
std::atomic_bool started_ = false;
fuchsia_hardware_hidbus::wire::HidBootProtocol boot_protocol_;
fbl::Array<const uint8_t> report_desc_;
static constexpr uint32_t mtu_ = 256; // TODO: set this based on report_desc_
fbl::Mutex lock_;
zx::socket data_;
void HandleData(async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
const zx_packet_signal_t* signal);
async::WaitMethod<HidDevice, &HidDevice::HandleData> wait_handler_{this};
std::array<uint8_t, mtu_> buf_;
};
} // namespace hidctl
#endif // SRC_UI_INPUT_DRIVERS_HIDCTL_HIDCTL_H_