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 #include <iostream>
16 #include <sstream>
17 #include <map>
18 #include <string>
19 #include <set>
20 
21 #include "usb_host_manager.h"
22 #include "common_event_data.h"
23 #include "common_event_manager.h"
24 #include "common_event_support.h"
25 #include "hilog_wrapper.h"
26 #include "hisysevent.h"
27 #include "cJSON.h"
28 #include "usb_serial_reader.h"
29 #include "usb_device.h"
30 #include "usb_config.h"
31 #include "usb_interface.h"
32 #include "usb_errors.h"
33 
34 #ifdef USB_NOTIFICATION_ENABLE
35 #include "usb_mass_storage_notification.h"
36 #endif
37 
38 using namespace OHOS::AAFwk;
39 using namespace OHOS::EventFwk;
40 using namespace OHOS::HiviewDFX;
41 
42 namespace OHOS {
43 namespace USB {
44 constexpr int32_t CLASS_PRINT_LENGTH = 2;
45 constexpr int32_t USAGE_IN_INTERFACE_CLASS = 0;
46 constexpr uint8_t DES_USAGE_IN_INTERFACE = 0x02;
47 std::map<int32_t, DeviceClassUsage> deviceUsageMap = {
48     {0x00, {DeviceClassUsage(2, "Use class information in the Interface Descriptors")}},
49     {0x01, {DeviceClassUsage(2, "Audio")}},
50     {0x02, {DeviceClassUsage(3, "Communications and CDC Control")}},
51     {0x03, {DeviceClassUsage(2, "HID(Human Interface Device)")}},
52     {0x05, {DeviceClassUsage(2, "Physical")}},
53     {0x06, {DeviceClassUsage(2, "Image")}},
54     {0x07, {DeviceClassUsage(2, "Printer")}},
55     {0x08, {DeviceClassUsage(2, "Mass Storage")}},
56     {0x09, {DeviceClassUsage(1, "Hub")}},
57     {0x0a, {DeviceClassUsage(2, "CDC-Data")}},
58     {0x0b, {DeviceClassUsage(2, "Smart Card")}},
59     {0x0d, {DeviceClassUsage(2, "Content Security")}},
60     {0x0e, {DeviceClassUsage(2, "Video")}},
61     {0x0f, {DeviceClassUsage(2, "Personal Healthcare")}},
62     {0x10, {DeviceClassUsage(2, "Audio/Video Device")}},
63     {0x11, {DeviceClassUsage(1, "Billboard Device Class")}},
64     {0x12, {DeviceClassUsage(2, "USB Type-C Bridge Class")}}
65 };
66 
67 std::map<UsbDeviceType, std::string> interfaceUsageMap = {
68     {{UsbDeviceType(0x03, 0x01, 0x01, 0)}, "KeyBoard"},
69     {{UsbDeviceType(0x03, 0x01, 0x02, 0)}, "Mouse/Table/Touch screen"},
70 };
UsbHostManager(SystemAbility * systemAbility)71 UsbHostManager::UsbHostManager(SystemAbility *systemAbility)
72 {
73     systemAbility_ = systemAbility;
74 }
75 
~UsbHostManager()76 UsbHostManager::~UsbHostManager()
77 {
78     for (auto &pair : devices_) {
79         delete pair.second;
80     }
81     devices_.clear();
82 }
83 
GetDevices(MAP_STR_DEVICE & devices)84 void UsbHostManager::GetDevices(MAP_STR_DEVICE &devices)
85 {
86     devices = devices_;
87 }
88 
GetProductName(const std::string & deviceName,std::string & productName)89 bool UsbHostManager::GetProductName(const std::string &deviceName, std::string &productName)
90 {
91     auto iter = devices_.find(deviceName);
92     if (iter == devices_.end()) {
93         return false;
94     }
95 
96     UsbDevice *dev = iter->second;
97     if (dev == nullptr) {
98         return false;
99     }
100 
101     productName = dev->GetProductName();
102     return true;
103 }
104 
DelDevice(uint8_t busNum,uint8_t devNum)105 bool UsbHostManager::DelDevice(uint8_t busNum, uint8_t devNum)
106 {
107     std::string name = std::to_string(busNum) + "-" + std::to_string(devNum);
108     MAP_STR_DEVICE::iterator iter = devices_.find(name);
109     if (iter == devices_.end()) {
110         USB_HILOGF(MODULE_SERVICE, "name:%{public}s bus:%{public}hhu dev:%{public}hhu not exist", name.c_str(), busNum,
111             devNum);
112         return false;
113     }
114     USB_HILOGI(
115         MODULE_SERVICE, "device:%{public}s bus:%{public}hhu dev:%{public}hhu erase ", name.c_str(), busNum, devNum);
116     UsbDevice *devOld = iter->second;
117     if (devOld == nullptr) {
118         USB_HILOGE(MODULE_SERVICE, "invalid device");
119         return false;
120     }
121 
122     auto isSuccess = PublishCommonEvent(CommonEventSupport::COMMON_EVENT_USB_DEVICE_DETACHED, *devOld);
123     if (!isSuccess) {
124         USB_HILOGW(MODULE_SERVICE, "send device attached broadcast failed");
125     }
126 #ifdef USB_NOTIFICATION_ENABLE
127     UsbMassStorageNotification::GetInstance()->CancelNotification(devices_, *devOld, name);
128 #endif
129 
130     delete devOld;
131     devices_.erase(iter);
132     return true;
133 }
134 
AddDevice(UsbDevice * dev)135 bool UsbHostManager::AddDevice(UsbDevice *dev)
136 {
137     if (dev == nullptr) {
138         USB_HILOGF(MODULE_SERVICE, "device is NULL");
139         return false;
140     }
141 
142     auto isSuccess = PublishCommonEvent(CommonEventSupport::COMMON_EVENT_USB_DEVICE_ATTACHED, *dev);
143     if (!isSuccess) {
144         USB_HILOGW(MODULE_SERVICE, "send device attached broadcast failed");
145     }
146 
147     uint8_t busNum = dev->GetBusNum();
148     uint8_t devNum = dev->GetDevAddr();
149     std::string name = std::to_string(busNum) + "-" + std::to_string(devNum);
150     MAP_STR_DEVICE::iterator iter = devices_.find(name);
151     if (iter != devices_.end()) {
152         USB_HILOGF(MODULE_SERVICE, "device:%{public}s bus:%{public}hhu dev:%{public}hhu already exist", name.c_str(),
153             busNum, devNum);
154         UsbDevice *devOld = iter->second;
155         if (devOld != nullptr && devOld != dev) {
156             delete devOld;
157         }
158         devices_.erase(iter);
159     }
160     USB_HILOGI(
161         MODULE_SERVICE, "device:%{public}s bus:%{public}hhu dev:%{public}hhu insert", name.c_str(), busNum, devNum);
162     devices_.insert(std::pair<std::string, UsbDevice *>(name, dev));
163 
164 #ifdef USB_NOTIFICATION_ENABLE
165     UsbMassStorageNotification::GetInstance()->SendNotification(*dev);
166 #endif
167     return true;
168 }
169 
PublishCommonEvent(const std::string & event,const UsbDevice & dev)170 bool UsbHostManager::PublishCommonEvent(const std::string &event, const UsbDevice &dev)
171 {
172     Want want;
173     want.SetAction(event);
174     CommonEventData data(want);
175     data.SetData(dev.getJsonString().c_str());
176     CommonEventPublishInfo publishInfo;
177     USB_HILOGI(MODULE_SERVICE, "send %{public}s broadcast device:%{public}s", event.c_str(),
178         dev.getJsonString().c_str());
179     ReportHostPlugSysEvent(event, dev);
180     return CommonEventManager::PublishCommonEvent(data, publishInfo);
181 }
182 
Dump(int fd,const std::string & args)183 bool UsbHostManager::Dump(int fd, const std::string &args)
184 {
185     if (args.compare("-a") != 0) {
186         dprintf(fd, "args is not -a\n");
187         return false;
188     }
189 
190     dprintf(fd, "Usb Host all device list info:\n");
191     for (const auto &item : devices_) {
192         dprintf(fd, "usb host list info: %s\n", item.second->getJsonString().c_str());
193     }
194     return true;
195 }
196 
GetDeviceDescription(int32_t baseClass,std::string & description,uint8_t & usage)197 int32_t UsbHostManager::GetDeviceDescription(int32_t baseClass, std::string &description, uint8_t &usage)
198 {
199     auto iter = deviceUsageMap.find(baseClass);
200     if (iter != deviceUsageMap.end()) {
201         description = iter->second.description;
202         usage = iter->second.usage;
203     } else {
204         description = "NA";
205         usage = 1;
206     }
207     return UEC_OK;
208 }
209 
210 
ConcatenateToDescription(const UsbDeviceType & interfaceType,const std::string & str)211 std::string UsbHostManager::ConcatenateToDescription(const UsbDeviceType &interfaceType, const std::string& str)
212 {
213     std::stringstream ss;
214     ss << std::setw(CLASS_PRINT_LENGTH) << std::setfill('0') << std::hex << interfaceType.baseClass << "_";
215     ss << std::setw(CLASS_PRINT_LENGTH) << std::setfill('0') << std::hex << interfaceType.subClass << "_";
216     ss << std::setw(CLASS_PRINT_LENGTH) << std::setfill('0') << std::hex << interfaceType.protocol << ",";
217     ss << str;
218     return ss.str();
219 }
220 
GetInterfaceUsageDescription(const UsbDeviceType & interfaceType)221 std::string UsbHostManager::GetInterfaceUsageDescription(const UsbDeviceType &interfaceType)
222 {
223     std::string infUsageDes = "NA";
224     auto infUsageIter = interfaceUsageMap.find(interfaceType);
225     if (infUsageIter != interfaceUsageMap.end()) {
226         return infUsageIter->second;
227     }
228     return infUsageDes;
229 }
230 
GetInterfaceDescription(const UsbDevice & dev,std::string & description,int32_t & baseClass)231 int32_t UsbHostManager::GetInterfaceDescription(const UsbDevice &dev, std::string &description, int32_t &baseClass)
232 {
233     std::set<UsbDeviceType> useInterfaceType;
234     for (int32_t i = 0; i < dev.GetConfigCount(); i++) {
235         USBConfig config;
236         dev.GetConfig(i, config);
237         for (uint32_t j = 0; j < config.GetInterfaceCount(); j++) {
238             if (i != 0 || j != 0) {
239                 description += ";";
240             }
241             UsbInterface interface;
242             config.GetInterface(j, interface);
243             baseClass = interface.GetClass();
244             UsbDeviceType interfaceType = {interface.GetClass(),
245                 interface.GetSubClass(), interface.GetProtocol(), 0};
246             if (useInterfaceType.find(interfaceType) == useInterfaceType.end()) {
247                 useInterfaceType.insert(interfaceType);
248                 std::string infUsageDes = GetInterfaceUsageDescription(interfaceType);
249                 description += ConcatenateToDescription(interfaceType, infUsageDes);
250             }
251         }
252     }
253     return UEC_OK;
254 }
255 
ReportHostPlugSysEvent(const std::string & event,const UsbDevice & dev)256 void UsbHostManager::ReportHostPlugSysEvent(const std::string &event, const UsbDevice &dev)
257 {
258     std::string deviceUsageDes;
259     uint8_t deviceUsage = 0;
260     GetDeviceDescription(dev.GetClass(), deviceUsageDes, deviceUsage);
261     std::string extUsageDes;
262     int32_t intfBaseClass = 0;
263     if (deviceUsage & DES_USAGE_IN_INTERFACE) {
264         GetInterfaceDescription(dev, extUsageDes, intfBaseClass);
265     }
266 
267     if (dev.GetClass() == USAGE_IN_INTERFACE_CLASS) {
268         GetDeviceDescription(intfBaseClass, deviceUsageDes, deviceUsage);
269     }
270     USB_HILOGI(MODULE_SERVICE, "Host mode Indicates the insertion and removal information");
271     HiSysEventWrite(HiSysEvent::Domain::USB, "PLUG_IN_OUT_HOST_MODE", HiSysEvent::EventType::BEHAVIOR,
272         "DEVICE_NAME", dev.GetName(), "DEVICE_PROTOCOL", dev.GetProtocol(),
273         "DEVICE_SUBCLASS", dev.GetSubclass(), "DEVICE_CLASS", dev.GetClass(),
274         "DEVICE_CLASS_DESCRIPTION", deviceUsageDes, "INTERFACE_CLASS_DESCRIPTION", extUsageDes,
275         "VENDOR_ID", dev.GetVendorId(), "PRODUCT_ID", dev.GetProductId(),
276         "VERSION", dev.GetVersion(), "EVENT_NAME", event);
277 }
278 } // namespace USB
279 } // namespace OHOS
280