1 /*
2  * Copyright (c) 2023 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 <cstdint>
17 #include <cstring>
18 #include <vector>
19 #include <algorithm>
20 #include <unordered_map>
21 #include "hid_ddk_api.h"
22 #include "hid_ddk_types.h"
23 #include "v1_0/ihid_ddk.h"
24 #include "hilog_wrapper.h"
25 #include <iproxy_broker.h>
26 
27 using namespace OHOS;
28 using namespace OHOS::ExternalDeviceManager;
29 namespace {
30 static OHOS::sptr<OHOS::HDI::Input::Ddk::V1_0::IHidDdk> g_ddk = nullptr;
31 static OHOS::sptr<IRemoteObject::DeathRecipient> recipient_ = nullptr;
32 std::mutex g_mutex;
33 constexpr uint32_t MAX_EMIT_ITEM_NUM = 20;
34 constexpr uint32_t MAX_HID_DEVICE_PROP_LEN = 7;
35 constexpr uint32_t MAX_HID_EVENT_TYPES_LEN = 5;
36 constexpr uint32_t MAX_HID_KEYS_LEN = 100;
37 constexpr uint32_t MAX_HID_ABS_LEN = 26;
38 constexpr uint32_t MAX_HID_REL_BITS_LEN = 13;
39 constexpr uint32_t MAX_HID_MISC_EVENT_LEN = 6;
40 constexpr uint32_t MAX_NAME_LENGTH = 80;
41 }
42 #ifdef __cplusplus
43 extern "C" {
44 #endif /* __cplusplus */
45 static std::unordered_map<int32_t, std::shared_ptr<struct TempDevice>> g_deviceMap;
46 
47 struct TempDevice {
48     OHOS::HDI::Input::Ddk::V1_0::Hid_Device tempDevice;
49     OHOS::HDI::Input::Ddk::V1_0::Hid_EventProperties tempProperties;
50     uint32_t realId;
51 };
52 
53 class HidDeathRecipient : public IRemoteObject::DeathRecipient {
54 public:
55         void OnRemoteDied(const wptr<IRemoteObject> &object) override;
56 };
57 
OnRemoteDied(const wptr<IRemoteObject> & object)58 void HidDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
59 {
60     std::lock_guard<std::mutex> lock(g_mutex);
61     EDM_LOGI(MODULE_HID_DDK, "hid_ddk remote died");
62     if (g_ddk != nullptr) {
63         sptr<IRemoteObject> remote = OHOS::HDI::hdi_objcast<OHOS::HDI::Input::Ddk::V1_0::IHidDdk>(g_ddk);
64         remote->RemoveDeathRecipient(recipient_);
65         recipient_.clear();
66         g_ddk = nullptr;
67         EDM_LOGI(MODULE_HID_DDK, "remove death recipient success");
68     }
69 }
70 
GetRealDeviceId(int32_t deviceId)71 static uint32_t GetRealDeviceId(int32_t deviceId)
72 {
73     if (g_deviceMap.find(deviceId) != g_deviceMap.end()) {
74         if (g_deviceMap[deviceId] != nullptr) {
75             return g_deviceMap[deviceId]->realId;
76         }
77     }
78     return static_cast<uint32_t>(deviceId);
79 }
80 
Connect()81 static int32_t Connect()
82 {
83     if (g_ddk == nullptr) {
84         g_ddk = OHOS::HDI::Input::Ddk::V1_0::IHidDdk::Get();
85         if (g_ddk == nullptr) {
86             EDM_LOGE(MODULE_HID_DDK, "get hid ddk faild");
87             return HID_DDK_FAILURE;
88         }
89         if (g_deviceMap.size() > 0) {
90             for (const auto &[_, value] : g_deviceMap) {
91                 (void)g_ddk->CreateDevice(value->tempDevice, value->tempProperties, value->realId);
92             }
93         }
94         recipient_ = new HidDeathRecipient();
95         sptr<IRemoteObject> remote = OHOS::HDI::hdi_objcast<OHOS::HDI::Input::Ddk::V1_0::IHidDdk>(g_ddk);
96         if (!remote->AddDeathRecipient(recipient_)) {
97             EDM_LOGE(MODULE_HID_DDK, "add DeathRecipient failed");
98             return HID_DDK_FAILURE;
99         }
100     }
101     return HID_DDK_SUCCESS;
102 }
103 
ParseHidDevice(Hid_Device * hidDevice)104 static OHOS::HDI::Input::Ddk::V1_0::Hid_Device ParseHidDevice(Hid_Device *hidDevice)
105 {
106     OHOS::HDI::Input::Ddk::V1_0::Hid_Device tempDevice = {
107         .deviceName = hidDevice->deviceName,
108         .vendorId = hidDevice->vendorId,
109         .productId = hidDevice->productId,
110         .version = hidDevice->version,
111         .bustype = hidDevice->bustype
112     };
113 
114     if (hidDevice->properties != nullptr) {
115         std::transform(hidDevice->properties, hidDevice->properties + hidDevice->propLength,
116             std::back_inserter(tempDevice.properties), [](uint32_t n) {
117                 return static_cast<OHOS::HDI::Input::Ddk::V1_0::Hid_DeviceProp>(n);
118             });
119     }
120 
121     return tempDevice;
122 }
123 
ParseHidEventProperties(Hid_EventProperties * hidEventProperties)124 static OHOS::HDI::Input::Ddk::V1_0::Hid_EventProperties ParseHidEventProperties(Hid_EventProperties *hidEventProperties)
125 {
126     const uint16_t absLength = 64;
127     OHOS::HDI::Input::Ddk::V1_0::Hid_EventProperties tempProperties = {
128         .hidAbsMax = std::vector<int32_t>(hidEventProperties->hidAbsMax, hidEventProperties->hidAbsMax + absLength),
129         .hidAbsMin = std::vector<int32_t>(hidEventProperties->hidAbsMin, hidEventProperties->hidAbsMin + absLength),
130         .hidAbsFuzz = std::vector<int32_t>(hidEventProperties->hidAbsFuzz, hidEventProperties->hidAbsFuzz + absLength),
131         .hidAbsFlat = std::vector<int32_t>(hidEventProperties->hidAbsFlat, hidEventProperties->hidAbsFlat + absLength)
132     };
133 
134     if (hidEventProperties->hidEventTypes.hidEventType != nullptr) {
135         std::transform(hidEventProperties->hidEventTypes.hidEventType,
136             hidEventProperties->hidEventTypes.hidEventType + hidEventProperties->hidEventTypes.length,
137             std::back_inserter(tempProperties.hidEventTypes), [](uint32_t n) {
138                 return static_cast<OHOS::HDI::Input::Ddk::V1_0::Hid_EventType>(n);
139             });
140     }
141 
142     if (hidEventProperties->hidKeys.hidKeyCode != nullptr) {
143         std::transform(hidEventProperties->hidKeys.hidKeyCode,
144             hidEventProperties->hidKeys.hidKeyCode + hidEventProperties->hidKeys.length,
145             std::back_inserter(tempProperties.hidKeys), [](uint32_t n) {
146                 return static_cast<OHOS::HDI::Input::Ddk::V1_0::Hid_KeyCode>(n);
147             });
148     }
149 
150     if (hidEventProperties->hidAbs.hidAbsAxes != nullptr) {
151         std::transform(hidEventProperties->hidAbs.hidAbsAxes,
152             hidEventProperties->hidAbs.hidAbsAxes + hidEventProperties->hidAbs.length,
153             std::back_inserter(tempProperties.hidAbs), [](uint32_t n) {
154                 return static_cast<OHOS::HDI::Input::Ddk::V1_0::Hid_AbsAxes>(n);
155             });
156     }
157 
158     if (hidEventProperties->hidRelBits.hidRelAxes != nullptr) {
159         std::transform(hidEventProperties->hidRelBits.hidRelAxes,
160             hidEventProperties->hidRelBits.hidRelAxes + hidEventProperties->hidRelBits.length,
161             std::back_inserter(tempProperties.hidRelBits), [](uint32_t n) {
162                 return static_cast<OHOS::HDI::Input::Ddk::V1_0::Hid_RelAxes>(n);
163             });
164     }
165 
166     if (hidEventProperties->hidMiscellaneous.hidMscEvent != nullptr) {
167         std::transform(hidEventProperties->hidMiscellaneous.hidMscEvent,
168             hidEventProperties->hidMiscellaneous.hidMscEvent + hidEventProperties->hidMiscellaneous.length,
169             std::back_inserter(tempProperties.hidMiscellaneous), [](uint32_t n) {
170                 return static_cast<OHOS::HDI::Input::Ddk::V1_0::Hid_MscEvent>(n);
171             });
172     }
173 
174     return tempProperties;
175 }
176 
CacheDeviceInfor(OHOS::HDI::Input::Ddk::V1_0::Hid_Device tempDevice,OHOS::HDI::Input::Ddk::V1_0::Hid_EventProperties tempProperties,uint32_t deviceId)177 static int32_t CacheDeviceInfor(OHOS::HDI::Input::Ddk::V1_0::Hid_Device tempDevice,
178     OHOS::HDI::Input::Ddk::V1_0::Hid_EventProperties tempProperties, uint32_t deviceId)
179 {
180     EDM_LOGD(MODULE_HID_DDK, "enter CacheDeviceInfor");
181     int32_t id = static_cast<int32_t>(deviceId);
182     std::shared_ptr<struct TempDevice> device = std::make_shared<struct TempDevice>();
183     device->tempDevice = tempDevice;
184     device->tempProperties = tempProperties;
185     device->realId = deviceId;
186 
187     g_deviceMap[id] = device;
188     return id;
189 }
190 
CheckHidDevice(Hid_Device * hidDevice)191 static bool CheckHidDevice(Hid_Device *hidDevice)
192 {
193     if (hidDevice == nullptr) {
194         EDM_LOGE(MODULE_HID_DDK, "hidDevice is null");
195         return false;
196     }
197 
198     if (hidDevice->propLength > MAX_HID_DEVICE_PROP_LEN) {
199         EDM_LOGE(MODULE_HID_DDK, "properties length is out of range");
200         return false;
201     }
202 
203     if (hidDevice->deviceName == nullptr) {
204         EDM_LOGE(MODULE_HID_DDK, "hidDevice->deviceName is nullpointer");
205         return false;
206     }
207 
208     if (strlen(hidDevice->deviceName) == 0 || strlen(hidDevice->deviceName) > MAX_NAME_LENGTH - 1) {
209         EDM_LOGE(MODULE_HID_DDK, "length of hidDevice->deviceName is out of range");
210         return false;
211     }
212     return true;
213 }
214 
OH_Hid_CreateDevice(Hid_Device * hidDevice,Hid_EventProperties * hidEventProperties)215 int32_t OH_Hid_CreateDevice(Hid_Device *hidDevice, Hid_EventProperties *hidEventProperties)
216 {
217     std::lock_guard<std::mutex> lock(g_mutex);
218     if (Connect() != HID_DDK_SUCCESS) {
219         return HID_DDK_INVALID_OPERATION;
220     }
221 
222     if (!CheckHidDevice(hidDevice)) {
223         return HID_DDK_INVALID_PARAMETER;
224     }
225 
226     if (hidEventProperties == nullptr) {
227         EDM_LOGE(MODULE_HID_DDK, "hidEventProperties is null");
228         return HID_DDK_INVALID_PARAMETER;
229     }
230 
231     if (hidEventProperties->hidEventTypes.length > MAX_HID_EVENT_TYPES_LEN) {
232         EDM_LOGE(MODULE_HID_DDK, "hidEventTypes length is out of range");
233         return HID_DDK_INVALID_PARAMETER;
234     }
235 
236     if (hidEventProperties->hidKeys.length > MAX_HID_KEYS_LEN) {
237         EDM_LOGE(MODULE_HID_DDK, "hidKeys length is out of range");
238         return HID_DDK_INVALID_PARAMETER;
239     }
240 
241     if (hidEventProperties->hidAbs.length > MAX_HID_ABS_LEN) {
242         EDM_LOGE(MODULE_HID_DDK, "hidAbs length is out of range");
243         return HID_DDK_INVALID_PARAMETER;
244     }
245 
246     if (hidEventProperties->hidRelBits.length > MAX_HID_REL_BITS_LEN) {
247         EDM_LOGE(MODULE_HID_DDK, "hidRelBits length is out of range");
248         return HID_DDK_INVALID_PARAMETER;
249     }
250 
251     if (hidEventProperties->hidMiscellaneous.length > MAX_HID_MISC_EVENT_LEN) {
252         EDM_LOGE(MODULE_HID_DDK, "hidMiscellaneous length is out of range");
253         return HID_DDK_INVALID_PARAMETER;
254     }
255 
256     auto tempDevice = ParseHidDevice(hidDevice);
257     auto tempEventProperties = ParseHidEventProperties(hidEventProperties);
258 
259     uint32_t deviceId = 0;
260     auto ret = g_ddk->CreateDevice(tempDevice, tempEventProperties, deviceId);
261     if (ret != HID_DDK_SUCCESS) {
262         EDM_LOGE(MODULE_HID_DDK, "create device failed:%{public}d", ret);
263         return ret;
264     }
265     return CacheDeviceInfor(tempDevice, tempEventProperties, deviceId);
266 }
267 
OH_Hid_EmitEvent(int32_t deviceId,const Hid_EmitItem items[],uint16_t length)268 int32_t OH_Hid_EmitEvent(int32_t deviceId, const Hid_EmitItem items[], uint16_t length)
269 {
270     std::lock_guard<std::mutex> lock(g_mutex);
271     if (Connect() != HID_DDK_SUCCESS) {
272         return HID_DDK_INVALID_OPERATION;
273     }
274 
275     if (deviceId < 0) {
276         EDM_LOGE(MODULE_HID_DDK, "device id is invaild");
277         return HID_DDK_INVALID_PARAMETER;
278     }
279 
280     if (length > MAX_EMIT_ITEM_NUM) {
281         EDM_LOGE(MODULE_HID_DDK, "items length is out of range");
282         return HID_DDK_INVALID_PARAMETER;
283     }
284 
285     if (items == nullptr) {
286         EDM_LOGE(MODULE_HID_DDK, "items is null");
287         return HID_DDK_INVALID_PARAMETER;
288     }
289 
290     std::vector<OHOS::HDI::Input::Ddk::V1_0::Hid_EmitItem> itemsTemp;
291     std::transform(items, items + length, std::back_inserter(itemsTemp), [](Hid_EmitItem item) {
292         return *reinterpret_cast<OHOS::HDI::Input::Ddk::V1_0::Hid_EmitItem *>(&item);
293     });
294 
295     auto ret = g_ddk->EmitEvent(GetRealDeviceId(deviceId), itemsTemp);
296     if (ret != HID_DDK_SUCCESS) {
297         EDM_LOGE(MODULE_HID_DDK, "emit event failed:%{public}d", ret);
298         return ret;
299     }
300     return HID_DDK_SUCCESS;
301 }
302 
OH_Hid_DestroyDevice(int32_t deviceId)303 int32_t OH_Hid_DestroyDevice(int32_t deviceId)
304 {
305     std::lock_guard<std::mutex> lock(g_mutex);
306     if (Connect() != HID_DDK_SUCCESS) {
307         return HID_DDK_INVALID_OPERATION;
308     }
309 
310     auto ret = g_ddk->DestroyDevice(GetRealDeviceId(deviceId));
311     if (ret != HID_DDK_SUCCESS) {
312         EDM_LOGE(MODULE_HID_DDK, "destroy device failed:%{public}d", ret);
313         return ret;
314     }
315 
316     g_deviceMap.erase(deviceId);
317     return HID_DDK_SUCCESS;
318 }
319 #ifdef __cplusplus
320 }
321 #endif /* __cplusplus */
322