1 /*
2  * Copyright (c) 2021-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 <regex>
17 #include "usb_device_manager.h"
18 #include <hdf_base.h>
19 #include "common_event_data.h"
20 #include "common_event_manager.h"
21 #include "common_event_support.h"
22 #include "hisysevent.h"
23 #include "usb_errors.h"
24 #include "usb_srv_support.h"
25 #include "usbd_type.h"
26 
27 using namespace OHOS::AAFwk;
28 using namespace OHOS::EventFwk;
29 using namespace OHOS::HiviewDFX;
30 using namespace OHOS::HDI::Usb::V1_0;
31 
32 namespace OHOS {
33 namespace USB {
34 constexpr int32_t PARAM_COUNT_TWO = 2;
35 constexpr int32_t PARAM_COUNT_THR = 3;
36 constexpr uint32_t CMD_INDEX = 1;
37 constexpr uint32_t PARAM_INDEX = 2;
38 constexpr uint32_t DELAY_DISCONN_INTERVAL = 1 * 1000;
39 const std::map<std::string_view, uint32_t> UsbDeviceManager::FUNCTION_MAPPING_N2C = {
40     {UsbSrvSupport::FUNCTION_NAME_NONE, UsbSrvSupport::FUNCTION_NONE},
41     {UsbSrvSupport::FUNCTION_NAME_ACM, UsbSrvSupport::FUNCTION_ACM},
42     {UsbSrvSupport::FUNCTION_NAME_ECM, UsbSrvSupport::FUNCTION_ECM},
43     {UsbSrvSupport::FUNCTION_NAME_HDC, UsbSrvSupport::FUNCTION_HDC},
44     {UsbSrvSupport::FUNCTION_NAME_MTP, UsbSrvSupport::FUNCTION_MTP},
45     {UsbSrvSupport::FUNCTION_NAME_PTP, UsbSrvSupport::FUNCTION_PTP},
46     {UsbSrvSupport::FUNCTION_NAME_RNDIS, UsbSrvSupport::FUNCTION_RNDIS},
47     {UsbSrvSupport::FUNCTION_NAME_STORAGE, UsbSrvSupport::FUNCTION_STORAGE},
48 };
49 
UsbDeviceManager()50 UsbDeviceManager::UsbDeviceManager()
51 {
52     USB_HILOGI(MODULE_USB_SERVICE, "UsbDeviceManager::Init start");
53     usbd_ = IUsbInterface::Get();
54     if (usbd_ == nullptr) {
55         USB_HILOGE(MODULE_USB_SERVICE, "UsbDeviceManager::Get inteface failed");
56     }
57 }
58 
Init()59 int32_t UsbDeviceManager::Init()
60 {
61     std::shared_ptr<UsbFunctionSwitchWindow> window_ = UsbFunctionSwitchWindow::GetInstance();
62     if (window_ == nullptr) {
63         USB_HILOGE(MODULE_USB_SERVICE, "get usb function switch window failed");
64         return UEC_SERVICE_INNER_ERR;
65     }
66 
67     int32_t ret = window_->Init();
68     if (ret != UEC_OK) {
69         USB_HILOGE(MODULE_USB_SERVICE, "Init usb function switch window failed");
70     }
71     return ret;
72 }
73 
SetUsbd(const sptr<IUsbInterface> &usbd)74 int32_t UsbDeviceManager::SetUsbd(const sptr<IUsbInterface> &usbd)
75 {
76     if (usbd == nullptr) {
77         USB_HILOGE(MODULE_USB_SERVICE, "UsbDeviceManager usbd is nullptr");
78         return UEC_SERVICE_INVALID_VALUE;
79     }
80     usbd_ = usbd;
81     return UEC_OK;
82 }
83 
AreSettableFunctions(int32_t funcs)84 bool UsbDeviceManager::AreSettableFunctions(int32_t funcs)
85 {
86     return static_cast<uint32_t>(funcs) == UsbSrvSupport::FUNCTION_NONE ||
87         ((~functionSettable_ & static_cast<uint32_t>(funcs)) == 0);
88 }
89 
ConvertFromString(std::string_view strFun)90 uint32_t UsbDeviceManager::ConvertFromString(std::string_view strFun)
91 {
92     if (strFun == UsbSrvSupport::FUNCTION_NAME_NONE) {
93         return UsbSrvSupport::FUNCTION_NONE;
94     }
95 
96     size_t len = strFun.length();
97     if (len == 0) {
98         return UEC_SERVICE_INVALID_VALUE;
99     }
100 
101     std::vector<std::string_view> vModeStr;
102     size_t pos = 0;
103     while (pos < len) {
104         size_t findPos = strFun.find(",", pos);
105         if (findPos == strFun.npos) {
106             vModeStr.push_back(strFun.substr(pos, len - pos));
107             break;
108         }
109         vModeStr.push_back(strFun.substr(pos, findPos - pos));
110         pos = findPos + 1;
111     }
112 
113     uint32_t ret = 0;
114     for (auto &&item : vModeStr) {
115         auto it = FUNCTION_MAPPING_N2C.find(item);
116         if (it != FUNCTION_MAPPING_N2C.end()) {
117             ret |= it->second;
118         } else {
119             USB_HILOGE(MODULE_USB_SERVICE, "UsbDeviceManager::ConvertFromString Invalid argument of usb function");
120             return UEC_SERVICE_INVALID_VALUE;
121         }
122     }
123 
124     return ret;
125 }
126 
ConvertToString(uint32_t function)127 std::string UsbDeviceManager::ConvertToString(uint32_t function)
128 {
129     std::string stream;
130     if (function <= UsbSrvSupport::FUNCTION_NONE || function > functionSettable_) {
131         stream = std::string {UsbSrvSupport::FUNCTION_NAME_NONE};
132         return stream;
133     }
134     bool flag = false;
135     for (auto it = FUNCTION_MAPPING_N2C.begin(); it != FUNCTION_MAPPING_N2C.end(); ++it) {
136         if ((function & it->second) != 0) {
137             if (flag) {
138                 stream += ",";
139             }
140             stream += std::string {it->first};
141             flag = true;
142         }
143     }
144     USB_HILOGI(MODULE_USB_SERVICE, "UsbDeviceManager::ConvertToString success");
145     return stream;
146 }
147 
UpdateFunctions(int32_t func)148 void UsbDeviceManager::UpdateFunctions(int32_t func)
149 {
150     ReportFuncChangeSysEvent(currentFunctions_, func);
151     currentFunctions_ = func;
152 }
153 
GetCurrentFunctions()154 int32_t UsbDeviceManager::GetCurrentFunctions()
155 {
156     return currentFunctions_;
157 }
158 
HandleEvent(int32_t status)159 void UsbDeviceManager::HandleEvent(int32_t status)
160 {
161     if (usbd_ == nullptr) {
162         USB_HILOGE(MODULE_USB_SERVICE, "UsbDeviceManager::usbd_ is nullptr");
163         return;
164     }
165     bool curConnect = false;
166     switch (status) {
167         case ACT_UPDEVICE: {
168             curConnect = true;
169             gadgetConnected_ = true;
170             break;
171         }
172         case ACT_DOWNDEVICE: {
173             curConnect = false;
174             gadgetConnected_ = false;
175             break;
176         }
177         default:
178             USB_HILOGE(MODULE_USB_SERVICE, "invalid status %{public}d", status);
179             curConnect = false;
180     }
181     delayDisconn_.Unregister(delayDisconnTimerId_);
182     delayDisconn_.Shutdown();
183     if (curConnect && (connected_ != curConnect)) {
184         connected_ = curConnect;
185         usbd_->GetCurrentFunctions(currentFunctions_);
186         ProcessFuncChange(connected_, currentFunctions_);
187     } else if (!curConnect && (connected_ != curConnect)) {
188         auto task = [&]() {
189             connected_ = false;
190             ProcessFuncChange(connected_, currentFunctions_);
191             return;
192         };
193         auto ret = delayDisconn_.Setup();
194         if (ret != UEC_OK) {
195             USB_HILOGE(MODULE_USB_SERVICE, "set up timer failed %{public}u", ret);
196             return;
197         }
198         delayDisconnTimerId_ = delayDisconn_.Register(task, DELAY_DISCONN_INTERVAL, true);
199     } else {
200         USB_HILOGI(MODULE_USB_SERVICE, "else info cur status %{public}d, bconnected: %{public}d", status, connected_);
201     }
202 }
203 
ProcessFuncChange(bool connected, int32_t currentFunc)204 void UsbDeviceManager::ProcessFuncChange(bool connected, int32_t currentFunc)
205 {
206     USB_HILOGI(MODULE_USB_SERVICE, "Current Connect %{public}d,bconnected: %{public}d", connected, currentFunc);
207     Want want;
208     want.SetAction(CommonEventSupport::COMMON_EVENT_USB_STATE);
209 
210     want.SetParam(std::string {UsbSrvSupport::CONNECTED}, connected);
211     uint32_t remainderFunc = static_cast<uint32_t>(currentFunc);
212     // start from bit 1
213     uint32_t bit = 1;
214     while (remainderFunc != 0) {
215         if (remainderFunc & bit) {
216             want.SetParam(ConvertToString(bit), true);
217             // set current bit to zero
218             remainderFunc &= ~bit;
219         }
220         // 1 means to next bit
221         bit = bit << 1;
222     }
223     CommonEventData data(want);
224     CommonEventPublishInfo publishInfo;
225     USB_HILOGI(MODULE_SERVICE, "send COMMON_EVENT_USB_STATE broadcast connected:%{public}d, "
226         "currentFunctions:%{public}d", connected, currentFunc);
227     CommonEventManager::PublishCommonEvent(data, publishInfo);
228     ReportDevicePlugSysEvent(currentFunc, connected);
229     ProcessFunctionSwitchWindow(connected);
230 }
231 
ProcessFunctionSwitchWindow(bool connected)232 void UsbDeviceManager::ProcessFunctionSwitchWindow(bool connected)
233 {
234     std::shared_ptr<UsbFunctionSwitchWindow> window_ = UsbFunctionSwitchWindow::GetInstance();
235     if (window_ == nullptr) {
236         USB_HILOGE(MODULE_USB_SERVICE, "show window: get usb function switch window failed");
237         return;
238     }
239 
240     if (connected) {
241         USB_HILOGD(MODULE_USB_SERVICE, "start pop up usb service switch window");
242         if (!window_->PopUpFunctionSwitchWindow()) {
243             USB_HILOGE(MODULE_USB_SERVICE, "start pop up usb service switch window failed");
244         }
245     } else {
246         USB_HILOGD(MODULE_USB_SERVICE, "start dismiss usb service switch window");
247         if (!window_->DismissFunctionSwitchWindow()) {
248             USB_HILOGE(MODULE_USB_SERVICE, "start dismiss usb service switch window failed");
249         }
250     }
251 }
252 
GetDumpHelp(int32_t fd)253 void UsbDeviceManager::GetDumpHelp(int32_t fd)
254 {
255     dprintf(fd, "========= dump the all device function =========\n");
256     dprintf(fd, "usb_device -a:    Query all function\n");
257     dprintf(fd, "usb_device -f Q:  Query Current function\n");
258     dprintf(fd, "usb_device -f 0:  Switch to function:none\n");
259     dprintf(fd, "usb_device -f 1:  Switch to function:acm\n");
260     dprintf(fd, "usb_device -f 2:  Switch to function:ecm\n");
261     dprintf(fd, "usb_device -f 3:  Switch to function:acm&ecm\n");
262     dprintf(fd, "usb_device -f 4:  Switch to function:hdc\n");
263     dprintf(fd, "usb_device -f 5:  Switch to function:acm&hdc\n");
264     dprintf(fd, "usb_device -f 6:  Switch to function:ecm&hdc\n");
265     dprintf(fd, "usb_device -f 32: Switch to function:rndis\n");
266     dprintf(fd, "usb_device -f 512:Switch to function:storage\n");
267     dprintf(fd, "usb_device -f 36: Switch to function:rndis&hdc\n");
268     dprintf(fd, "usb_device -f 516:Switch to function:storage&hdc\n");
269     dprintf(fd, "------------------------------------------------\n");
270 }
271 
DumpGetSupportFunc(int32_t fd)272 void UsbDeviceManager::DumpGetSupportFunc(int32_t fd)
273 {
274     dprintf(fd, "Usb Device function list info:\n");
275     dprintf(fd, "current function: %s\n", ConvertToString(currentFunctions_).c_str());
276     dprintf(fd, "supported functions list: %s\n", ConvertToString(functionSettable_).c_str());
277 }
278 
DumpSetFunc(int32_t fd, const std::string &args)279 void UsbDeviceManager::DumpSetFunc(int32_t fd, const std::string &args)
280 {
281     int32_t currentFunction;
282     int32_t ret;
283     if (usbd_ == nullptr) {
284         USB_HILOGE(MODULE_USB_SERVICE, "UsbDeviceManager::DumpSetFunc usbd_ is nullptr");
285         return;
286     }
287     if (args.compare("Q") == 0) {
288         ret = usbd_->GetCurrentFunctions(currentFunction);
289         if (ret != UEC_OK) {
290             dprintf(fd, "GetCurrentFunctions failed: %d\n", __LINE__);
291             return;
292         }
293         dprintf(fd, "current function: %s\n", ConvertToString(currentFunction).c_str());
294         return;
295     }
296     if (!std::regex_match(args, std::regex("^[0-9]+$"))) {
297         dprintf(fd, "Invalid input, please enter a valid integer\n");
298         GetDumpHelp(fd);
299         return;
300     }
301     int32_t mode = stoi(args);
302     ret = usbd_->SetCurrentFunctions(mode);
303     if (ret != UEC_OK) {
304         dprintf(fd, "SetCurrentFunctions failed");
305         return;
306     }
307     ret = usbd_->GetCurrentFunctions(currentFunction);
308     if (ret != UEC_OK) {
309         dprintf(fd, "GetCurrentFunctions failed: %d\n", __LINE__);
310         return;
311     }
312 
313     dprintf(fd, "current function: %s\n", ConvertToString(currentFunction).c_str());
314 }
315 
Dump(int32_t fd, const std::vector<std::string> &args)316 void UsbDeviceManager::Dump(int32_t fd, const std::vector<std::string> &args)
317 {
318     if (args.size() < PARAM_COUNT_TWO || args.size() > PARAM_COUNT_THR) {
319         GetDumpHelp(fd);
320         return;
321     }
322 
323     if (args[CMD_INDEX] == "-a" && args.size() == PARAM_COUNT_TWO) {
324         DumpGetSupportFunc(fd);
325     } else if (args[CMD_INDEX] == "-f" && args.size() == PARAM_COUNT_THR) {
326         DumpSetFunc(fd, args[PARAM_INDEX]);
327     } else {
328         dprintf(fd, "func param error, please enter again\n");
329         GetDumpHelp(fd);
330     }
331 }
332 
ReportFuncChangeSysEvent(int32_t currentFunctions, int32_t updateFunctions)333 void UsbDeviceManager::ReportFuncChangeSysEvent(int32_t currentFunctions, int32_t updateFunctions)
334 {
335     USB_HILOGI(MODULE_USB_SERVICE, "Device function Indicates the switch point information:");
336     HiSysEventWrite(HiSysEvent::Domain::USB, "FUNCTION_CHANGED",
337         HiSysEvent::EventType::BEHAVIOR, "CURRENT_FUNCTION",
338         currentFunctions_, "UPDATE_FUNCTION", updateFunctions);
339 }
340 
ReportDevicePlugSysEvent(int32_t currentFunctions, bool connected)341 void UsbDeviceManager::ReportDevicePlugSysEvent(int32_t currentFunctions, bool connected)
342 {
343     USB_HILOGI(MODULE_USB_SERVICE, "Device mode Indicates the insertion and removal information:");
344     HiSysEventWrite(HiSysEvent::Domain::USB, "PLUG_IN_OUT_DEVICE_MODE",
345         HiSysEvent::EventType::BEHAVIOR, "CURRENT_FUNCTIONS",
346         currentFunctions, "CONNECTED", connected);
347 }
IsGadgetConnected(void)348 bool UsbDeviceManager::IsGadgetConnected(void)
349 {
350     return gadgetConnected_;
351 }
352 } // namespace USB
353 } // namespace OHOS
354