/* * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. * 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 "usbd_accessory.h" #include <cerrno> #include <unistd.h> #include <securec.h> #include "hdf_base.h" #include "hdf_log.h" #include "usbd_wrapper.h" #include "usbd_type.h" namespace OHOS { namespace HDI { namespace Usb { namespace V1_1 { const char *ACCESSORY_DRIVER_NAME = "/dev/usb_accessory"; constexpr int BUFFER_SIZE = 256; static const std::vector<int32_t> accStringList = { ACCESSORY_GET_STRING_MANUFACTURER, ACCESSORY_GET_STRING_MODEL, ACCESSORY_GET_STRING_DESCRIPTION, ACCESSORY_GET_STRING_VERSION, ACCESSORY_GET_STRING_SERIAL, AOA_GET_EXTRA_DATA }; const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; static const uint32_t BASE64_VAL_SHIFT = 8; static const int32_t MIN_LENGTH_REQUIRED = 10; const int INDEX_FIRST = 0; const int INDEX_SECOND = 1; const int INDEX_THIRD = 2; const int INDEX_FORTH = 3; const int INDEX_FIFTH = 4; const uint8_t PARAM_FC = 0xfc; const uint8_t PARAM_03 = 0x03; const uint8_t PARAM_F0 = 0xf0; const uint8_t PARAM_0F = 0x0f; const uint8_t PARAM_C0 = 0xc0; const uint8_t PARAM_3F = 0x3f; const uint32_t OFFSET2 = 2; const uint32_t OFFSET4 = 4; const uint32_t OFFSET6 = 6; UsbdAccessory &UsbdAccessory::GetInstance() { static UsbdAccessory instance; return instance; } void UsbdAccessory::init_base64_char_map() { for (size_t i = 0; i < base64_chars.size(); ++i) { base64_char_map[base64_chars[i]] = static_cast<int>(i); } } std::string UsbdAccessory::base64_encode(char *buffer, int32_t len) { if (buffer == nullptr) { HDF_LOGE("%{public}s: buffer is nullptr", __func__); return ""; } std::string ret; uint32_t i = 0; uint8_t charArray3[INDEX_FORTH]; uint8_t charArray4[INDEX_FIFTH]; while (len > 0) { charArray3[i++] = *(buffer++); if (i == sizeof(charArray3)) { charArray4[INDEX_FIRST] = (charArray3[INDEX_FIRST] & PARAM_FC) >> OFFSET2; charArray4[INDEX_SECOND] = ((charArray3[INDEX_FIRST] & PARAM_03) << OFFSET4) + ((charArray3[INDEX_SECOND] & PARAM_F0) >> OFFSET4); charArray4[INDEX_THIRD] = ((charArray3[INDEX_SECOND] & PARAM_0F) << OFFSET2) + ((charArray3[INDEX_THIRD] & PARAM_C0) >> OFFSET6); charArray4[INDEX_FORTH] = charArray3[INDEX_THIRD] & PARAM_3F; for (i = 0; i < sizeof(charArray4); i++) { ret += base64_chars[charArray4[i]]; } i = 0; } len--; } if (i == 0) { return ret; } if (i) { uint32_t j = 0; for (j = i; j < sizeof(charArray3); j++) { charArray3[j] = '\0'; } charArray4[INDEX_FIRST] = (charArray3[INDEX_FIRST] & PARAM_FC) >> OFFSET2; charArray4[INDEX_SECOND] = ((charArray3[INDEX_FIRST] & PARAM_03) << OFFSET4) + ((charArray3[INDEX_SECOND] & PARAM_F0) >> OFFSET4); charArray4[INDEX_THIRD] = ((charArray3[INDEX_SECOND] & PARAM_0F) << OFFSET2) + ((charArray3[INDEX_THIRD] & PARAM_C0) >> OFFSET6); charArray4[INDEX_FORTH] = charArray3[INDEX_THIRD] & PARAM_3F; for (j = 0; j < i + 1; j++) { ret += base64_chars[charArray4[j]]; } while (i < sizeof(charArray3)) { ret += '='; i++; } } return ret; } int32_t UsbdAccessory::ExtraToString(char* buffer, int32_t len, std::string &extraData) { if (buffer == nullptr) { HDF_LOGE("%{public}s: buffer is nullptr", __func__); return HDF_FAILURE; } if (len < MIN_LENGTH_REQUIRED) { return HDF_FAILURE; } int16_t actLen = *(buffer + BASE64_VAL_SHIFT); actLen = actLen >= len ? len: actLen; if (base64_char_map.empty()) { init_base64_char_map(); } extraData = base64_encode(buffer, actLen); return HDF_SUCCESS; } int32_t UsbdAccessory::GetAccessoryString(int32_t fd, int32_t cmd, std::string &accInfoString) { char buffer[BUFFER_SIZE]; if (memset_s(buffer, BUFFER_SIZE, 0, BUFFER_SIZE) != HDF_SUCCESS) { HDF_LOGE("%{public}s:%{public}d memset_s failed", __func__, __LINE__); return HDF_FAILURE; } int32_t ret = ioctl(fd, cmd, buffer); if (ret < 0) { HDF_LOGE("%{public}s:%{public}d ioctl failed, ret: %{public}d", __func__, __LINE__, ret); return ret; } accInfoString = buffer; if (cmd == AOA_GET_EXTRA_DATA) { return ExtraToString(buffer, ret, accInfoString); } return HDF_SUCCESS; } int32_t UsbdAccessory::GetAccessoryInfo(std::vector<std::string> &accessoryInfo) { int32_t fd = open(ACCESSORY_DRIVER_NAME, O_RDWR); if (fd < 0) { HDF_LOGE("%{public}s:%{public}d open failed", __func__, __LINE__); return HDF_FAILURE; } int32_t ret = HDF_FAILURE; std::string accInfoString; for (size_t i = 0; i < accStringList.size(); i++) { ret = GetAccessoryString(fd, accStringList[i], accInfoString); if (ret != HDF_SUCCESS) { HDF_LOGE("%{public}s:%{public}d SetAccessoryString failed", __func__, __LINE__); continue; } accessoryInfo.push_back(accInfoString); } close(fd); return HDF_SUCCESS; } int32_t UsbdAccessory::OpenAccessory(int32_t &fd) { if (accFd > 0) { fd = accFd; return HDF_ERR_DEVICE_BUSY; } accFd = open(ACCESSORY_DRIVER_NAME, O_RDWR); if (accFd < 0) { HDF_LOGE("%{public}s:%{public}d open failed", __func__, __LINE__); return HDF_FAILURE; } fd = accFd; return HDF_SUCCESS; } int32_t UsbdAccessory::CloseAccessory(int32_t fd) { if (accFd > 0) { close(accFd); } close(fd); accFd = 0; return HDF_SUCCESS; } void UsbdAccessory::HandleEvent(int32_t state) { if (state == ACT_DOWNDEVICE && accFd > 0) { close(accFd); accFd = 0; } } } // namespace V1_1 } // namespace Usb } // namespace HDI } // namespace OHOS