1 /*
2 * Copyright (C) 2022 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_host_uhid.h"
17 #include "hid_host_service.h"
18 #include "log_util.h"
19
20 namespace OHOS {
21 namespace bluetooth {
HidHostUhid(std::string address)22 HidHostUhid::HidHostUhid(std::string address)
23 {
24 address_ = address;
25 pollThreadId_ = -1;
26 fd_ = -1;
27 keepPolling_ = false;
28 readyForData_ = false;
29 task_id_ = 0;
30 }
31
~HidHostUhid()32 HidHostUhid::~HidHostUhid()
33 {
34 Close();
35 Destroy();
36 }
37
Open()38 int HidHostUhid::Open()
39 {
40 pthread_t threadId;
41
42 if (fd_ < 0) {
43 LOG_INFO("[UHID]%{public}s():fd is null,creat fd", __FUNCTION__);
44 fd_ = open(UHID_DEVICE_PATH, O_RDWR);
45 if (fd_ < 0) {
46 LOG_ERROR("[UHID]%{public}s():open %{public}s failed", __FUNCTION__, UHID_DEVICE_PATH);
47 return HID_HOST_FAILURE;
48 } else {
49 LOG_INFO("[UHID]%{public}s():uhid fd = %{public}d", __FUNCTION__, fd_);
50 }
51
52 LOG_INFO("[UHID]%{public}s():recreate thread", __FUNCTION__);
53 threadId = CreateThread(PollEventThread, this);
54 if (threadId == static_cast<pthread_t>(-1)) {
55 LOG_ERROR("[UHID]%{public}s():create thread failed", __FUNCTION__);
56 return HID_HOST_FAILURE;
57 } else {
58 pollThreadId_ = threadId;
59 return HID_HOST_SUCCESS;
60 }
61 }
62
63 LOG_INFO("[UHID]%{public}s():uhid fd is not null,fd = %{public}d", __FUNCTION__, fd_);
64 return HID_HOST_SUCCESS;
65 }
66
Close()67 int HidHostUhid::Close()
68 {
69 ClosePollThread();
70 return HID_HOST_SUCCESS;
71 }
72
SendData(uint8_t * pRpt,uint16_t len)73 int HidHostUhid::SendData(uint8_t* pRpt, uint16_t len)
74 {
75 LOG_INFO("[UHID]%{public}s", __FUNCTION__);
76 if (fd_ >= 0) {
77 uint32_t polling_attempts = 0;
78 while (!readyForData_ && polling_attempts < MAX_POLLING_ATTEMPTS) {
79 usleep(POLLING_SLEEP_DURATION_US);
80 polling_attempts++;
81 }
82 }
83 // Send the HID data to the kernel.
84 if ((fd_ >= 0) && readyForData_) {
85 WritePackUhid(fd_, pRpt, len);
86 } else {
87 LOG_ERROR("[UHID]%{public}s failed, fd_:%{public}d, readyForData_:%{public}d, len:%{public}d",
88 __FUNCTION__, fd_, readyForData_, len);
89 return HID_HOST_FAILURE;
90 }
91 return HID_HOST_SUCCESS;
92 }
93
SendControlData(uint8_t * pRpt,uint16_t len)94 int HidHostUhid::SendControlData(uint8_t* pRpt, uint16_t len)
95 {
96 LOG_INFO("[UHID]%{public}s", __FUNCTION__);
97 if (fd_ >= 0) {
98 uint32_t polling_attempts = 0;
99 while (!readyForData_ && polling_attempts < MAX_POLLING_ATTEMPTS) {
100 usleep(POLLING_SLEEP_DURATION_US);
101 polling_attempts++;
102 }
103 }
104 // Send the HID control data to the kernel.
105 if ((fd_ >= 0) && readyForData_) {
106 if (task_type_ == HID_HOST_DATA_TYPE_GET_REPORT) {
107 SendGetReportReplyUhid(fd_, task_id_, HID_HOST_SUCCESS, pRpt, len);
108 } else if (task_type_ == HID_HOST_DATA_TYPE_SET_REPORT) {
109 SendSetReportReplyUhid(fd_, task_id_, HID_HOST_SUCCESS);
110 } else {
111 LOG_ERROR("[UHID]%{public}s, Unknow task_type_:%{public}d", __FUNCTION__, task_type_);
112 }
113 task_id_ = 0;
114 task_type_ = -1;
115 } else {
116 LOG_ERROR("[UHID]%{public}s failed, fd_:%{public}d, readyForData_:%{public}d, len:%{public}d",
117 __FUNCTION__, fd_, readyForData_, len);
118 return HID_HOST_FAILURE;
119 }
120 return HID_HOST_SUCCESS;
121 }
122
SendHandshake(uint16_t err)123 int HidHostUhid::SendHandshake(uint16_t err)
124 {
125 LOG_INFO("[UHID]%{public}s, err:%{public}d", __FUNCTION__, err);
126 if (fd_ >= 0) {
127 uint32_t polling_attempts = 0;
128 while (!readyForData_ && polling_attempts < MAX_POLLING_ATTEMPTS) {
129 usleep(POLLING_SLEEP_DURATION_US);
130 polling_attempts++;
131 }
132 }
133 // Send the HID handshake to the kernel.
134 if ((fd_ >= 0) && readyForData_) {
135 if (task_type_ == HID_HOST_DATA_TYPE_GET_REPORT) {
136 SendGetReportReplyUhid(fd_, task_id_, err, nullptr, 0);
137 } else if (task_type_ == HID_HOST_DATA_TYPE_SET_REPORT) {
138 SendSetReportReplyUhid(fd_, task_id_, err);
139 } else {
140 LOG_ERROR("[UHID]%{public}s, Unknow task_type_:%{public}d", __FUNCTION__, task_type_);
141 }
142 task_id_ = 0;
143 task_type_ = -1;
144 } else {
145 LOG_ERROR("[UHID]%{public}s failed, fd_:%{public}d, readyForData_:%{public}d",
146 __FUNCTION__, fd_, readyForData_);
147 return HID_HOST_FAILURE;
148 }
149 return HID_HOST_SUCCESS;
150 }
151
SendGetReportReplyUhid(int fd,int id,uint16_t err,uint8_t * rpt,uint16_t len)152 int HidHostUhid::SendGetReportReplyUhid(int fd, int id, uint16_t err, uint8_t* rpt, uint16_t len)
153 {
154 struct uhid_event ev;
155 memset_s(&ev, sizeof(ev), 0, sizeof(ev));
156 ev.type = UHID_FEATURE_ANSWER;
157 ev.u.feature_answer.id = id;
158 ev.u.feature_answer.err = err;
159 ev.u.feature_answer.size = len;
160 if (len > sizeof(ev.u.feature_answer.data)) {
161 LOG_WARN("[UHID]%{public}s(): Report size greater than allowed size", __FUNCTION__);
162 return HID_HOST_FAILURE;
163 }
164 if (memcpy_s(ev.u.feature_answer.data, sizeof(ev.u.feature_answer.data), rpt, len) != EOK) {
165 LOG_ERROR("[UHID] %{public}s() memcpy error", __FUNCTION__);
166 return HID_HOST_FAILURE;
167 }
168 return WriteUhid(fd, &ev);
169 }
170
SendSetReportReplyUhid(int fd,int id,uint16_t err)171 int HidHostUhid::SendSetReportReplyUhid(int fd, int id, uint16_t err)
172 {
173 struct uhid_event ev;
174 memset_s(&ev, sizeof(ev), 0, sizeof(ev));
175 ev.type = UHID_SET_REPORT_REPLY;
176 ev.u.set_report_reply.id = id;
177 ev.u.set_report_reply.err = err;
178 return WriteUhid(fd, &ev);
179 }
180
SendHidInfo(const char * devName,PnpInformation & pnpInf,HidInformation & hidInf)181 int HidHostUhid::SendHidInfo(const char* devName, PnpInformation& pnpInf, HidInformation& hidInf)
182 {
183 struct uhid_event ev;
184 int ret ;
185
186 if (fd_ < 0) {
187 LOG_WARN("[UHID]%{public}s(): Error: fd = %{public}d, dscp_len = %{public}d", __FUNCTION__, fd_,
188 hidInf.descLength);
189 return HID_HOST_FAILURE;
190 }
191 // Create and send hid descriptor to kernel
192 memset_s(&ev, sizeof(ev), 0, sizeof(ev));
193 ev.type = UHID_CREATE;
194 if (strncpy_s((char*)ev.u.create.name, sizeof(ev.u.create.name), devName, sizeof(ev.u.create.name) - 1)
195 != EOK) {
196 LOG_ERROR("[UHID]%{public}s(): memcpy error", __FUNCTION__);
197 }
198 int uniqLength = snprintf_s(reinterpret_cast<char*>(ev.u.create.uniq), sizeof(ev.u.create.uniq), address_.length(),
199 "%s", address_.c_str());
200 if (uniqLength < 0) {
201 LOG_ERROR("[UHID]%{public}s(): snprintf length error, uniqLength = %{public}d", __FUNCTION__, uniqLength);
202 }
203 ev.u.create.rd_size = hidInf.descLength;
204 ev.u.create.rd_data = hidInf.descInfo.get();
205 ev.u.create.bus = BUS_BLUETOOTH;
206 ev.u.create.vendor = pnpInf.vendorId;
207 ev.u.create.product = pnpInf.productId;
208 ev.u.create.version = pnpInf.version;
209 ev.u.create.country = hidInf.ctryCode;
210 ret = WriteUhid(fd_, &ev);
211
212 LOG_INFO("[UHID]%{public}s(): wrote descriptor to fd = %{public}d, dscp_len = %{public}d,result = %{public}d",
213 __FUNCTION__, fd_, hidInf.descLength, ret);
214
215 if (ret) {
216 LOG_ERROR("[UHID]%{public}s(): Error: failed to send DSCP, result = %{public}d", __FUNCTION__, ret);
217 /* The HID report descriptor is corrupted. Close the driver. */
218 close(fd_);
219 fd_ = -1;
220 return HID_HOST_FAILURE;
221 }
222
223 return HID_HOST_SUCCESS;
224 }
225
Destroy()226 int HidHostUhid::Destroy()
227 {
228 if (fd_ >= 0) {
229 struct uhid_event ev;
230 memset_s(&ev, sizeof(ev), 0, sizeof(ev));
231 ev.type = UHID_DESTROY;
232
233 WriteUhid(fd_, &ev);
234 LOG_INFO("[UHID]%{public}s(): Closing fd=%{public}d", __FUNCTION__, fd_);
235 close(fd_);
236 fd_ = -1;
237 }
238 return HID_HOST_SUCCESS;
239 }
240
WriteUhid(int fd,const struct uhid_event * ev)241 int HidHostUhid::WriteUhid(int fd, const struct uhid_event* ev)
242 {
243 ssize_t ret;
244 do {
245 } while ((ret = write(fd, ev, sizeof(*ev))) == -1 && errno == EINTR);
246 if (ret < 0) {
247 int rtn = errno;
248 LOG_ERROR("[UHID]%{public}s(): Cannot write to uhid:%{public}s", __FUNCTION__, strerror(errno));
249 return rtn;
250 } else if (ret != static_cast<ssize_t>(sizeof(*ev))) {
251 LOG_ERROR("[UHID]%{public}s(): Wrong size written to uhid: %{public}zd != %{public}zu", __FUNCTION__,
252 ret, sizeof(*ev));
253 return EFAULT;
254 }
255 return HID_HOST_SUCCESS;
256 }
257
WritePackUhid(int fd,uint8_t * rpt,uint16_t len)258 int HidHostUhid::WritePackUhid(int fd, uint8_t* rpt, uint16_t len)
259 {
260 struct uhid_event ev;
261 memset_s(&ev, sizeof(ev), 0, sizeof(ev));
262 ev.type = UHID_INPUT;
263 ev.u.input.size = len;
264 if (len > sizeof(ev.u.input.data)) {
265 LOG_WARN("[UHID]%{public}s(): Report size greater than allowed size", __FUNCTION__);
266 return HID_HOST_FAILURE;
267 }
268 if (memcpy_s(ev.u.input.data, sizeof(ev.u.input.data), rpt, len) != EOK) {
269 LOG_ERROR("[UHID]%{public}s(): memcpy error", __FUNCTION__);
270 return HID_HOST_FAILURE;
271 }
272 return WriteUhid(fd, &ev);
273 }
274
ClosePollThread()275 int HidHostUhid::ClosePollThread()
276 {
277 LOG_INFO("[UHID]%{public}s():", __FUNCTION__);
278 readyForData_ = false;
279 if (keepPolling_) {
280 keepPolling_ = false;
281 pthread_join(pollThreadId_, nullptr);
282 }
283 pollThreadId_ = -1;
284 return HID_HOST_SUCCESS;
285 }
286
CreateThread(void * (* startRoutine)(void *),void * arg)287 pthread_t HidHostUhid::CreateThread(void* (*startRoutine)(void*), void* arg)
288 {
289 LOG_INFO("[UHID]%{public}s():create_thread: entered", __FUNCTION__);
290 pthread_attr_t threadAttr;
291
292 pthread_attr_init(&threadAttr);
293 pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_JOINABLE);
294 pthread_t threadId = static_cast<pthread_t>(-1);
295 if (pthread_create(&threadId, &threadAttr, startRoutine, arg) != 0) {
296 LOG_ERROR("[UHID]%{public}s():pthread_create : %{public}s", __FUNCTION__, strerror(errno));
297 return static_cast<pthread_t>(-1);
298 }
299 LOG_INFO("[UHID]%{public}s():%{public}lu: threadcreated successfully", __FUNCTION__, threadId);
300 return threadId;
301 }
302
PollEventThread(void * arg)303 void* HidHostUhid::PollEventThread(void* arg)
304 {
305 HidHostUhid *uhid = (HidHostUhid*)arg;
306 if (uhid != nullptr) {
307 uhid->PollEventThread_();
308 } else {
309 LOG_ERROR("[UHID]%{public}s():Thread creat fail,uhid is null", __FUNCTION__);
310 }
311 return nullptr;
312 }
313
PollEventThread_()314 void HidHostUhid::PollEventThread_()
315 {
316 HILOGI("Thread:%{public}d, fd:%{public}d execute", static_cast<int>(pollThreadId_), fd_);
317 struct pollfd pfds[1];
318 keepPolling_ = true;
319 pfds[0].fd = fd_;
320 pfds[0].events = POLLIN;
321
322 // Set the uhid fd as non-blocking to ensure we never block the BTU thread
323 SetUhidNonBlocking(fd_);
324
325 while (keepPolling_) {
326 int ret;
327 do {
328 } while ((ret = poll(pfds, 1, POLL_TIMEOUT)) == -1 && errno == EINTR);
329 if (ret < 0) {
330 LOG_ERROR("[UHID]%{public}s(): Cannot poll for fds: %{public}s", __FUNCTION__,
331 strerror(errno));
332 break;
333 }
334 if (pfds[0].revents & POLLIN) {
335 LOG_INFO("[UHID]%{public}s(): POLLIN", __FUNCTION__);
336 ret = ReadUhidEvent();
337 if (ret != 0) {
338 break;
339 }
340 }
341 }
342 LOG_INFO("[UHID]%{public}s(): exit", __FUNCTION__);
343
344 pollThreadId_ = -1;
345 }
346
SetUhidNonBlocking(int fd)347 void HidHostUhid::SetUhidNonBlocking(int fd)
348 {
349 int opts = fcntl(fd, F_GETFL);
350 if (opts < 0) {
351 LOG_ERROR("[UHID]%{public}s(): Getting flags failed (%{public}s)", __FUNCTION__, strerror(errno));
352 return;
353 }
354
355 if (fcntl(fd, F_SETFL, opts | O_NONBLOCK) < 0) {
356 LOG_ERROR("[UHID]%{public}s(): Setting non-blocking flag failed (%{public}s)", __FUNCTION__, strerror(errno));
357 }
358 }
359
ReadUhidEvent()360 int HidHostUhid::ReadUhidEvent()
361 {
362 struct uhid_event ev;
363 ssize_t ret;
364
365 memset_s(&ev, sizeof(ev), 0, sizeof(ev));
366
367 do {
368 } while ((ret = read(fd_, &ev, sizeof(ev))) == -1 && errno == EINTR);
369
370 if (ret <= 0) {
371 LOG_ERROR("[UHID]%{public}s():read err", __FUNCTION__);
372 return HID_HOST_FAILURE;
373 }
374 LOG_INFO("[UHID]%{public}s():ev.type:%{public}d", __FUNCTION__, ev.type);
375
376 switch (ev.type) {
377 case UHID_START:
378 LOG_INFO("[UHID]%{public}s():UHID_START from uhid-dev", __FUNCTION__);
379 readyForData_ = true;
380 break;
381 case UHID_STOP:
382 LOG_INFO("[UHID]%{public}s():UHID_STOP from uhid-dev", __FUNCTION__);
383 readyForData_ = false;
384 break;
385 case UHID_OPEN:
386 LOG_INFO("[UHID]%{public}s():UHID_OPEN from uhid-dev", __FUNCTION__);
387 readyForData_ = true;
388 break;
389 case UHID_CLOSE:
390 LOG_INFO("[UHID]%{public}s():UHID_CLOSE from uhid-dev", __FUNCTION__);
391 readyForData_ = false;
392 break;
393 case UHID_OUTPUT:
394 ReadUhidOutPut(ev);
395 break;
396 case UHID_OUTPUT_EV:
397 LOG_INFO("[UHID]%{public}s():UHID_OUTPUT_EV from uhid-dev", __FUNCTION__);
398 break;
399 case UHID_FEATURE:
400 ReadUhidFeature(ev);
401 break;
402 case UHID_SET_REPORT:
403 ReadUhidSetReport(ev);
404 break;
405 default:
406 LOG_INFO("[UHID]%{public}s():Invalid event from uhid-dev: %{public}u", __FUNCTION__, ev.type);
407 }
408
409 return HID_HOST_SUCCESS;
410 }
411
ReadUhidOutPut(uhid_event ev)412 void HidHostUhid::ReadUhidOutPut(uhid_event ev)
413 {
414 if (ev.u.output.rtype == UHID_FEATURE_REPORT) {
415 HidHostService::GetService()->HidHostSetReport(address_, HID_HOST_FEATURE_REPORT, ev.u.output.size,
416 ev.u.output.data);
417 } else if (ev.u.output.rtype == UHID_OUTPUT_REPORT) {
418 HidHostService::GetService()->HidHostSetReport(address_, HID_HOST_OUTPUT_REPORT, ev.u.output.size,
419 ev.u.output.data);
420 } else {
421 HidHostService::GetService()->HidHostSetReport(address_, HID_HOST_INPUT_REPORT, ev.u.output.size,
422 ev.u.output.data);
423 }
424 }
425
ReadUhidFeature(uhid_event ev)426 void HidHostUhid::ReadUhidFeature(uhid_event ev)
427 {
428 LOG_INFO("[UHID]%{public}s():UHID_FEATURE from uhid-dev id=%{public}d,rnum=%{public}d,rtype=%{public}d",
429 __FUNCTION__, ev.u.feature.id, ev.u.feature.rnum, ev.u.feature.rtype);
430 if (ev.u.feature.rtype == UHID_FEATURE_REPORT) {
431 HidHostService::GetService()->HidHostGetReport(address_, ev.u.feature.rnum, 0,
432 HID_HOST_FEATURE_REPORT);
433 } else if (ev.u.feature.rtype == UHID_OUTPUT_REPORT) {
434 HidHostService::GetService()->HidHostGetReport(address_, ev.u.feature.rnum, 0,
435 HID_HOST_OUTPUT_REPORT);
436 } else {
437 HidHostService::GetService()->HidHostGetReport(address_, ev.u.feature.rnum, 0,
438 HID_HOST_INPUT_REPORT);
439 }
440 task_id_ = ev.u.feature.id;
441 task_type_ = HID_HOST_DATA_TYPE_GET_REPORT;
442 }
443
ReadUhidSetReport(uhid_event ev)444 void HidHostUhid::ReadUhidSetReport(uhid_event ev)
445 {
446 LOG_INFO("[UHID]%{public}s():UHID_SET_REPORT id=%{public}d,rnum=%{public}d,rtype=%{public}d,size=%{public}d",
447 __FUNCTION__, ev.u.set_report.id, ev.u.set_report.rnum, ev.u.set_report.rtype, ev.u.set_report.size);
448 if (ev.u.set_report.rtype == UHID_FEATURE_REPORT) {
449 HidHostService::GetService()->HidHostSetReport(address_, HID_HOST_FEATURE_REPORT, ev.u.set_report.size,
450 ev.u.set_report.data);
451 } else if (ev.u.set_report.rtype == UHID_OUTPUT_REPORT) {
452 HidHostService::GetService()->HidHostSetReport(address_, HID_HOST_OUTPUT_REPORT, ev.u.set_report.size,
453 ev.u.set_report.data);
454 } else {
455 HidHostService::GetService()->HidHostSetReport(address_, HID_HOST_INPUT_REPORT, ev.u.set_report.size,
456 ev.u.set_report.data);
457 }
458 task_id_ = ev.u.feature.id;
459 task_type_ = HID_HOST_DATA_TYPE_SET_REPORT;
460 }
461 } // namespace bluetooth
462 } // namespace OHOS
463