• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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