/* * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "hid_linux_adapter.h" #include #include "input_uhdf_log.h" #include #include #include #include #include #include #include #include #include #define HDF_LOG_TAG hid_linux_adapter namespace OHOS { namespace HDI { namespace Input { namespace Ddk { namespace V1_1 { #ifndef HIDIOCGINPUT #define HIDIOCGINPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0A, len) #endif #ifndef HIDIOCSOUTPUT #define HIDIOCSOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0B, len) #endif #ifndef HIDIOCGOUTPUT #define HIDIOCGOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0C, len) #endif #ifndef HIDIOCSINPUT #define HIDIOCSINPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x09, len) #endif int32_t LinuxHidOsAdapter::GetRawInfo(int32_t fd, HidRawDevInfo& rawDevInfo) { struct hidraw_devinfo info; int32_t result = memset_s(&info, sizeof(info), 0x0, sizeof(info)); if (result != 0) { HDF_LOGE("%{public}s memset_s(hidraw_devinfo) failed, result=%{public}d", __func__, result); return HID_DDK_MEMORY_ERROR; } int32_t ret = ioctl(fd, HIDIOCGRAWINFO, &info); if (ret < 0) { HDF_LOGE("%{public}s ioctl failed, errno=%{public}d", __func__, errno); return HID_DDK_IO_ERROR; } rawDevInfo.busType = info.bustype; rawDevInfo.vendor = info.vendor; rawDevInfo.product = info.product; return HID_DDK_SUCCESS; } int32_t LinuxHidOsAdapter::GetRawName(int32_t fd, std::vector& data) { if (data.empty()) { HDF_LOGE("%{public}s param data is empty", __func__); return HID_DDK_INVALID_PARAMETER; } int32_t ret = ioctl(fd, HIDIOCGRAWNAME(data.size()), data.data()); if (ret < 0) { HDF_LOGE("%{public}s ioctl failed, errno=%{public}d", __func__, errno); return HID_DDK_IO_ERROR; } return HID_DDK_SUCCESS; } int32_t LinuxHidOsAdapter::GetPhysicalAddress(int32_t fd, std::vector& data) { if (data.empty()) { HDF_LOGE("%{public}s param data is empty", __func__); return HID_DDK_INVALID_PARAMETER; } int32_t ret = ioctl(fd, HIDIOCGRAWPHYS(data.size()), data.data()); if (ret < 0) { HDF_LOGE("%{public}s ioctl failed, errno=%{public}d", __func__, errno); return HID_DDK_IO_ERROR; } return HID_DDK_SUCCESS; } int32_t LinuxHidOsAdapter::GetRawUniqueId(int32_t fd, std::vector& data) { if (data.empty()) { HDF_LOGE("%{public}s param data is empty", __func__); return HID_DDK_INVALID_PARAMETER; } int32_t ret = ioctl(fd, HIDIOCGRAWUNIQ(data.size()), data.data()); if (ret < 0) { HDF_LOGE("%{public}s ioctl failed, errno=%{public}d", __func__, errno); return HID_DDK_IO_ERROR; } return HID_DDK_SUCCESS; } int32_t LinuxHidOsAdapter::SendReport(int32_t fd, HidReportType reportType, const std::vector& data) { if (data.empty()) { HDF_LOGE("%{public}s param data is empty", __func__); return HID_DDK_INVALID_PARAMETER; } int req = 0; switch (reportType) { case HID_INPUT_REPORT: req = HIDIOCSINPUT(data.size()); break; case HID_OUTPUT_REPORT: req = HIDIOCSOUTPUT(data.size()); break; case HID_FEATURE_REPORT: req = HIDIOCSFEATURE(data.size()); break; default: HDF_LOGE("%{public}s: unsupported report type [%d]", __func__, reportType); return HID_DDK_INVALID_PARAMETER; } int32_t res = ioctl(fd, req, data.data()); if (res < 0) { HDF_LOGE("%{public}s ioctl failed, errno=%{public}d", __func__, errno); if (errno == EINVAL) { return HID_DDK_INVALID_OPERATION; } return HID_DDK_IO_ERROR; } return HID_DDK_SUCCESS; } int32_t LinuxHidOsAdapter::GetReport(int32_t fd, HidReportType reportType, std::vector& data) { if (data.empty()) { HDF_LOGE("%{public}s param data is empty", __func__); return HID_DDK_INVALID_PARAMETER; } int req = 0; switch (reportType) { case HID_INPUT_REPORT: req = HIDIOCGINPUT(data.size()); break; case HID_OUTPUT_REPORT: req = HIDIOCGOUTPUT(data.size()); break; case HID_FEATURE_REPORT: req = HIDIOCGFEATURE(data.size()); break; default: HDF_LOGE("%{public}s: unsupported report type [%d]", __func__, reportType); return HID_DDK_INVALID_PARAMETER; } int32_t res = ioctl(fd, req, data.data()); if (res < 0) { HDF_LOGE("%{public}s ioctl failed, errno=%{public}d", __func__, errno); if (errno == EINVAL) { return HID_DDK_INVALID_OPERATION; } return HID_DDK_IO_ERROR; } return HID_DDK_SUCCESS; } int32_t LinuxHidOsAdapter::GetReportDescriptor(int32_t fd, std::vector& data, uint32_t& bytesRead) { bytesRead = 0; uint32_t descSize = 0; int32_t ret = ioctl(fd, HIDIOCGRDESCSIZE, &descSize); if (ret < 0) { HDF_LOGE("%{public}s ioctl(HIDIOCGRDESCSIZE) failed, errno=%{public}d", __func__, errno); return HID_DDK_IO_ERROR; } struct hidraw_report_descriptor desc; int32_t result = memset_s(&desc, sizeof(desc), 0x0, sizeof(desc)); if (result != 0) { HDF_LOGE("%{public}s memset_s(hidraw_report_descriptor) failed, result=%{public}d", __func__, result); return HID_DDK_MEMORY_ERROR; } desc.size = descSize; ret = ioctl(fd, HIDIOCGRDESC, &desc); if (ret < 0) { HDF_LOGE("%{public}s ioctl(HIDIOCGRDESC) failed, errno=%{public}d", __func__, errno); return HID_DDK_IO_ERROR; } uint32_t tempSize = desc.size < data.size() ? desc.size : data.size(); ret = memcpy_s(data.data(), data.size(), desc.value, tempSize); if (ret < 0) { HDF_LOGE("%{public}s memcpy_s failed, ret=%{public}d, data.size=%{public}zu, tempSize=%{public}d", __func__, ret, data.size(), tempSize); return HID_DDK_MEMORY_ERROR; } bytesRead = tempSize; return HID_DDK_SUCCESS; } } // V1_1 } // Ddk } // Input } // HDI } // OHOS