1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <ddk/device.h>
8 #include <ddktl/device.h>
9 #include <ddktl/protocol/hidbus.h>
10 #include <fbl/mutex.h>
11 #include <fbl/unique_ptr.h>
12 #include <threads.h>
13 #include <zircon/compiler.h>
14 #include <zircon/device/hidctl.h>
15 #include <zircon/types.h>
16 #include <lib/zx/socket.h>
17 
18 namespace hidctl {
19 
20 class HidCtl : public ddk::Device<HidCtl, ddk::Ioctlable> {
21   public:
22     HidCtl(zx_device_t* device);
23 
24     void DdkRelease();
25     zx_status_t DdkIoctl(uint32_t op, const void* in_buf, size_t in_len, void* out_buf,
26                          size_t out_len, size_t* out_actual);
27 };
28 
29 class HidDevice : public ddk::Device<HidDevice, ddk::Unbindable>,
30                   public ddk::HidbusProtocol<HidDevice, ddk::base_protocol> {
31   public:
32     HidDevice(zx_device_t* device, const hid_ioctl_config* config, zx::socket data);
33 
34     void DdkRelease();
35     void DdkUnbind();
36 
37     zx_status_t HidbusQuery(uint32_t options, hid_info_t* info);
38     zx_status_t HidbusStart(const hidbus_ifc_t* ifc);
39     void HidbusStop();
40     zx_status_t HidbusGetDescriptor(uint8_t desc_type, void** data, size_t* len);
41     zx_status_t HidbusGetReport(uint8_t rpt_type, uint8_t rpt_id, void* data, size_t len,
42                                 size_t* out_len);
43     zx_status_t HidbusSetReport(uint8_t rpt_type, uint8_t rpt_id, const void* data, size_t len);
44     zx_status_t HidbusGetIdle(uint8_t rpt_id, uint8_t* duration);
45     zx_status_t HidbusSetIdle(uint8_t rpt_id, uint8_t duration);
46     zx_status_t HidbusGetProtocol(uint8_t* protocol);
47     zx_status_t HidbusSetProtocol(uint8_t protocol);
48 
49     int Thread();
50     void Shutdown();
51 
52   private:
53     zx_status_t Recv(uint8_t* buffer, uint32_t capacity);
54 
55     bool boot_device_;
56     uint8_t dev_class_;
57     fbl::unique_ptr<uint8_t[]> report_desc_;
58     size_t report_desc_len_ = 0;
59     uint32_t mtu_ = 256;  // TODO: set this based on report_desc_
60 
61     fbl::Mutex lock_;
62     ddk::HidbusIfcClient client_ __TA_GUARDED(lock_);
63     zx::socket data_;
64     thrd_t thread_;
65 };
66 
67 }  // namespace hidctl
68