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