1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hid_linux_adapter.h"
17
18 #include <hdf_base.h>
19 #include "input_uhdf_log.h"
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <iostream>
23 #include <sys/ioctl.h>
24 #include <linux/hiddev.h>
25 #include <linux/hidraw.h>
26 #include <poll.h>
27 #include <memory.h>
28 #include <securec.h>
29
30 #define HDF_LOG_TAG hid_linux_adapter
31
32 namespace OHOS {
33 namespace HDI {
34 namespace Input {
35 namespace Ddk {
36 namespace V1_1 {
37 #ifndef HIDIOCGINPUT
38 #define HIDIOCGINPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0A, len)
39 #endif
40 #ifndef HIDIOCSOUTPUT
41 #define HIDIOCSOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0B, len)
42 #endif
43 #ifndef HIDIOCGOUTPUT
44 #define HIDIOCGOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0C, len)
45 #endif
46 #ifndef HIDIOCSINPUT
47 #define HIDIOCSINPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x09, len)
48 #endif
49
GetRawInfo(int32_t fd,HidRawDevInfo & rawDevInfo)50 int32_t LinuxHidOsAdapter::GetRawInfo(int32_t fd, HidRawDevInfo& rawDevInfo)
51 {
52 struct hidraw_devinfo info;
53 int32_t result = memset_s(&info, sizeof(info), 0x0, sizeof(info));
54 if (result != 0) {
55 HDF_LOGE("%{public}s memset_s(hidraw_devinfo) failed, result=%{public}d", __func__, result);
56 return HID_DDK_MEMORY_ERROR;
57 }
58
59 int32_t ret = ioctl(fd, HIDIOCGRAWINFO, &info);
60 if (ret < 0) {
61 HDF_LOGE("%{public}s ioctl failed, errno=%{public}d", __func__, errno);
62 return HID_DDK_IO_ERROR;
63 }
64
65 rawDevInfo.busType = info.bustype;
66 rawDevInfo.vendor = info.vendor;
67 rawDevInfo.product = info.product;
68
69 return HID_DDK_SUCCESS;
70 }
71
GetRawName(int32_t fd,std::vector<uint8_t> & data)72 int32_t LinuxHidOsAdapter::GetRawName(int32_t fd, std::vector<uint8_t>& data)
73 {
74 if (data.empty()) {
75 HDF_LOGE("%{public}s param data is empty", __func__);
76 return HID_DDK_INVALID_PARAMETER;
77 }
78
79 int32_t ret = ioctl(fd, HIDIOCGRAWNAME(data.size()), data.data());
80 if (ret < 0) {
81 HDF_LOGE("%{public}s ioctl failed, errno=%{public}d", __func__, errno);
82 return HID_DDK_IO_ERROR;
83 }
84
85 return HID_DDK_SUCCESS;
86 }
87
GetPhysicalAddress(int32_t fd,std::vector<uint8_t> & data)88 int32_t LinuxHidOsAdapter::GetPhysicalAddress(int32_t fd, std::vector<uint8_t>& data)
89 {
90 if (data.empty()) {
91 HDF_LOGE("%{public}s param data is empty", __func__);
92 return HID_DDK_INVALID_PARAMETER;
93 }
94
95 int32_t ret = ioctl(fd, HIDIOCGRAWPHYS(data.size()), data.data());
96 if (ret < 0) {
97 HDF_LOGE("%{public}s ioctl failed, errno=%{public}d", __func__, errno);
98 return HID_DDK_IO_ERROR;
99 }
100
101 return HID_DDK_SUCCESS;
102 }
103
GetRawUniqueId(int32_t fd,std::vector<uint8_t> & data)104 int32_t LinuxHidOsAdapter::GetRawUniqueId(int32_t fd, std::vector<uint8_t>& data)
105 {
106 if (data.empty()) {
107 HDF_LOGE("%{public}s param data is empty", __func__);
108 return HID_DDK_INVALID_PARAMETER;
109 }
110
111 int32_t ret = ioctl(fd, HIDIOCGRAWUNIQ(data.size()), data.data());
112 if (ret < 0) {
113 HDF_LOGE("%{public}s ioctl failed, errno=%{public}d", __func__, errno);
114 return HID_DDK_IO_ERROR;
115 }
116
117 return HID_DDK_SUCCESS;
118 }
119
SendReport(int32_t fd,HidReportType reportType,const std::vector<uint8_t> & data)120 int32_t LinuxHidOsAdapter::SendReport(int32_t fd, HidReportType reportType, const std::vector<uint8_t>& data)
121 {
122 if (data.empty()) {
123 HDF_LOGE("%{public}s param data is empty", __func__);
124 return HID_DDK_INVALID_PARAMETER;
125 }
126
127 int req = 0;
128 switch (reportType) {
129 case HID_INPUT_REPORT:
130 req = HIDIOCSINPUT(data.size());
131 break;
132 case HID_OUTPUT_REPORT:
133 req = HIDIOCSOUTPUT(data.size());
134 break;
135 case HID_FEATURE_REPORT:
136 req = HIDIOCSFEATURE(data.size());
137 break;
138 default:
139 HDF_LOGE("%{public}s: unsupported report type [%d]", __func__, reportType);
140 return HID_DDK_INVALID_PARAMETER;
141 }
142
143 int32_t res = ioctl(fd, req, data.data());
144 if (res < 0) {
145 HDF_LOGE("%{public}s ioctl failed, errno=%{public}d", __func__, errno);
146 if (errno == EINVAL) {
147 return HID_DDK_INVALID_OPERATION;
148 }
149 return HID_DDK_IO_ERROR;
150 }
151
152 return HID_DDK_SUCCESS;
153 }
154
GetReport(int32_t fd,HidReportType reportType,std::vector<uint8_t> & data)155 int32_t LinuxHidOsAdapter::GetReport(int32_t fd, HidReportType reportType, std::vector<uint8_t>& data)
156 {
157 if (data.empty()) {
158 HDF_LOGE("%{public}s param data is empty", __func__);
159 return HID_DDK_INVALID_PARAMETER;
160 }
161
162 int req = 0;
163 switch (reportType) {
164 case HID_INPUT_REPORT:
165 req = HIDIOCGINPUT(data.size());
166 break;
167 case HID_OUTPUT_REPORT:
168 req = HIDIOCGOUTPUT(data.size());
169 break;
170 case HID_FEATURE_REPORT:
171 req = HIDIOCGFEATURE(data.size());
172 break;
173 default:
174 HDF_LOGE("%{public}s: unsupported report type [%d]", __func__, reportType);
175 return HID_DDK_INVALID_PARAMETER;
176 }
177
178 int32_t res = ioctl(fd, req, data.data());
179 if (res < 0) {
180 HDF_LOGE("%{public}s ioctl failed, errno=%{public}d", __func__, errno);
181 if (errno == EINVAL) {
182 return HID_DDK_INVALID_OPERATION;
183 }
184 return HID_DDK_IO_ERROR;
185 }
186
187 return HID_DDK_SUCCESS;
188 }
189
GetReportDescriptor(int32_t fd,std::vector<uint8_t> & data,uint32_t & bytesRead)190 int32_t LinuxHidOsAdapter::GetReportDescriptor(int32_t fd, std::vector<uint8_t>& data, uint32_t& bytesRead)
191 {
192 bytesRead = 0;
193
194 uint32_t descSize = 0;
195 int32_t ret = ioctl(fd, HIDIOCGRDESCSIZE, &descSize);
196 if (ret < 0) {
197 HDF_LOGE("%{public}s ioctl(HIDIOCGRDESCSIZE) failed, errno=%{public}d", __func__, errno);
198 return HID_DDK_IO_ERROR;
199 }
200
201 struct hidraw_report_descriptor desc;
202 int32_t result = memset_s(&desc, sizeof(desc), 0x0, sizeof(desc));
203 if (result != 0) {
204 HDF_LOGE("%{public}s memset_s(hidraw_report_descriptor) failed, result=%{public}d", __func__, result);
205 return HID_DDK_MEMORY_ERROR;
206 }
207
208 desc.size = descSize;
209 ret = ioctl(fd, HIDIOCGRDESC, &desc);
210 if (ret < 0) {
211 HDF_LOGE("%{public}s ioctl(HIDIOCGRDESC) failed, errno=%{public}d", __func__, errno);
212 return HID_DDK_IO_ERROR;
213 }
214
215 uint32_t tempSize = desc.size < data.size() ? desc.size : data.size();
216 ret = memcpy_s(data.data(), data.size(), desc.value, tempSize);
217 if (ret < 0) {
218 HDF_LOGE("%{public}s memcpy_s failed, ret=%{public}d, data.size=%{public}zu, tempSize=%{public}d", __func__,
219 ret, data.size(), tempSize);
220 return HID_DDK_MEMORY_ERROR;
221 }
222
223 bytesRead = tempSize;
224
225 return HID_DDK_SUCCESS;
226 }
227
228 } // V1_1
229 } // Ddk
230 } // Input
231 } // HDI
232 } // OHOS
233