1/* 2 * Copyright (c) 2024 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 <cerrno> 17#include <ashmem.h> 18#include <unordered_map> 19#include <mutex> 20#include "ddk_api.h" 21#include "ddk_types.h" 22#include "hilog_wrapper.h" 23 24#define PORT_MAX 7 25 26using namespace OHOS::ExternalDeviceManager; 27namespace { 28static std::unordered_map<int32_t, OHOS::sptr<OHOS::Ashmem>> g_shareMemoryMap; 29std::mutex g_mutex; 30} 31 32DDK_RetCode OH_DDK_CreateAshmem(const uint8_t *name, uint32_t size, DDK_Ashmem **ashmem) 33{ 34 if (name == nullptr) { 35 EDM_LOGE(MODULE_BASE_DDK, "invalid buffer name!"); 36 return DDK_INVALID_PARAMETER; 37 } 38 39 if (size == 0) { 40 EDM_LOGE(MODULE_BASE_DDK, "invalid buffer size!, size = %{public}d", size); 41 return DDK_INVALID_PARAMETER; 42 } 43 44 if (ashmem == nullptr) { 45 EDM_LOGE(MODULE_BASE_DDK, "invalid pointer of ashmem!"); 46 return DDK_INVALID_PARAMETER; 47 } 48 49 OHOS::sptr<OHOS::Ashmem> shareMemory = OHOS::Ashmem::CreateAshmem(reinterpret_cast<const char*>(name), size); 50 if (shareMemory == nullptr) { 51 EDM_LOGE(MODULE_BASE_DDK, "create ashmem failed! errno = %{public}d", errno); 52 return DDK_FAILURE; 53 } 54 55 int32_t fd = shareMemory->GetAshmemFd(); 56 DDK_Ashmem *ddkAshmem = new DDK_Ashmem({fd, nullptr, size, 0, size, 0}); 57 if (ddkAshmem == nullptr) { 58 EDM_LOGE(MODULE_BASE_DDK, "alloc ddk ashmem failed! errno = %{public}d", errno); 59 return DDK_FAILURE; 60 } 61 *ashmem = ddkAshmem; 62 63 std::lock_guard<std::mutex> lock(g_mutex); 64 g_shareMemoryMap[ddkAshmem->ashmemFd] = shareMemory; 65 return DDK_SUCCESS; 66} 67 68static DDK_RetCode AshmemValidityCheck(DDK_Ashmem *ashmem) 69{ 70 if (ashmem == nullptr) { 71 EDM_LOGE(MODULE_BASE_DDK, "ashmem is nullptr!"); 72 return DDK_NULL_PTR; 73 } 74 75 if (g_shareMemoryMap.find(ashmem->ashmemFd) == g_shareMemoryMap.end()) { 76 EDM_LOGE(MODULE_BASE_DDK, "ashmemFd dose not exist! error fd = %{public}d", ashmem->ashmemFd); 77 return DDK_FAILURE; 78 } 79 80 if (g_shareMemoryMap[ashmem->ashmemFd] == nullptr) { 81 EDM_LOGE(MODULE_BASE_DDK, "share memory dose not create!"); 82 return DDK_FAILURE; 83 } 84 85 return DDK_SUCCESS; 86} 87 88DDK_RetCode OH_DDK_MapAshmem(DDK_Ashmem *ashmem, const uint8_t ashmemMapType) 89{ 90 std::lock_guard<std::mutex> lock(g_mutex); 91 DDK_RetCode ret = AshmemValidityCheck(ashmem); 92 if (ret != DDK_SUCCESS) { 93 EDM_LOGE(MODULE_BASE_DDK, "%{public}s: check the validity of ashmem fail!", __func__); 94 return ret; 95 } 96 97 if (ashmemMapType > PORT_MAX) { 98 EDM_LOGE(MODULE_BASE_DDK, "%{public}s: the ashmemMapType is illegal ,ashmemMapType = %{public}u", 99 __func__, ashmemMapType); 100 return DDK_INVALID_OPERATION; 101 } 102 103 if (!g_shareMemoryMap[ashmem->ashmemFd]->MapAshmem(ashmemMapType)) { 104 EDM_LOGE(MODULE_BASE_DDK, "MapAshmem fail! errno = %{public}d", errno); 105 return DDK_INVALID_OPERATION; 106 } 107 108 ashmem->address = 109 reinterpret_cast<const uint8_t *>(g_shareMemoryMap[ashmem->ashmemFd]->ReadFromAshmem(ashmem->size, 0)); 110 return DDK_SUCCESS; 111} 112 113DDK_RetCode OH_DDK_UnmapAshmem(DDK_Ashmem *ashmem) 114{ 115 std::lock_guard<std::mutex> lock(g_mutex); 116 DDK_RetCode ret = AshmemValidityCheck(ashmem); 117 if (ret != DDK_SUCCESS) { 118 EDM_LOGE(MODULE_BASE_DDK, "%{public}s: check the validity of ashmem fail!", __func__); 119 return ret; 120 } 121 122 g_shareMemoryMap[ashmem->ashmemFd]->UnmapAshmem(); 123 ashmem->address = nullptr; 124 return DDK_SUCCESS; 125} 126 127DDK_RetCode OH_DDK_DestroyAshmem(DDK_Ashmem *ashmem) 128{ 129 std::lock_guard<std::mutex> lock(g_mutex); 130 DDK_RetCode ret = AshmemValidityCheck(ashmem); 131 if (ret != DDK_SUCCESS) { 132 EDM_LOGE(MODULE_BASE_DDK, "%{public}s: check the validity of ashmem fail!", __func__); 133 return ret; 134 } 135 136 g_shareMemoryMap.erase(ashmem->ashmemFd); 137 ashmem->address = nullptr; 138 delete ashmem; 139 ashmem = nullptr; 140 return DDK_SUCCESS; 141} 142