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
26 using namespace OHOS::ExternalDeviceManager;
27 namespace {
28 static std::unordered_map<int32_t, OHOS::sptr<OHOS::Ashmem>> g_shareMemoryMap;
29 std::mutex g_mutex;
30 }
31
OH_DDK_CreateAshmem(const uint8_t * name,uint32_t size,DDK_Ashmem ** ashmem)32 DDK_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
AshmemValidityCheck(DDK_Ashmem * ashmem)68 static 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
OH_DDK_MapAshmem(DDK_Ashmem * ashmem,const uint8_t ashmemMapType)88 DDK_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
OH_DDK_UnmapAshmem(DDK_Ashmem * ashmem)113 DDK_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
OH_DDK_DestroyAshmem(DDK_Ashmem * ashmem)127 DDK_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