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 38using namespace OHOS::AAFwk; 39using namespace OHOS::EventFwk; 40using namespace OHOS::HiviewDFX; 41 42namespace OHOS { 43namespace USB { 44constexpr int32_t CLASS_PRINT_LENGTH = 2; 45constexpr int32_t USAGE_IN_INTERFACE_CLASS = 0; 46constexpr uint8_t DES_USAGE_IN_INTERFACE = 0x02; 47std::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 67std::map<UsbDeviceType, std::string> interfaceUsageMap = { 68 {{UsbDeviceType(0x03, 0x01, 0x01, 0)}, "KeyBoard"}, 69 {{UsbDeviceType(0x03, 0x01, 0x02, 0)}, "Mouse/Table/Touch screen"}, 70}; 71UsbHostManager::UsbHostManager(SystemAbility *systemAbility) 72{ 73 systemAbility_ = systemAbility; 74} 75 76UsbHostManager::~UsbHostManager() 77{ 78 for (auto &pair : devices_) { 79 delete pair.second; 80 } 81 devices_.clear(); 82} 83 84void UsbHostManager::GetDevices(MAP_STR_DEVICE &devices) 85{ 86 devices = devices_; 87} 88 89bool 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 105bool 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 135bool 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 170bool 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 183bool 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 197int32_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 211std::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 221std::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 231int32_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 useInterfaceType.insert(interfaceType); 247 std::string infUsageDes = GetInterfaceUsageDescription(interfaceType); 248 description += ConcatenateToDescription(interfaceType, infUsageDes); 249 } 250 } 251 return UEC_OK; 252} 253 254void UsbHostManager::ReportHostPlugSysEvent(const std::string &event, const UsbDevice &dev) 255{ 256 std::string deviceUsageDes; 257 uint8_t deviceUsage = 0; 258 GetDeviceDescription(dev.GetClass(), deviceUsageDes, deviceUsage); 259 std::string extUsageDes; 260 int32_t intfBaseClass = 0; 261 if (deviceUsage & DES_USAGE_IN_INTERFACE) { 262 GetInterfaceDescription(dev, extUsageDes, intfBaseClass); 263 } 264 265 if (dev.GetClass() == USAGE_IN_INTERFACE_CLASS) { 266 GetDeviceDescription(intfBaseClass, deviceUsageDes, deviceUsage); 267 } 268 USB_HILOGI(MODULE_SERVICE, "Host mode Indicates the insertion and removal information"); 269 HiSysEventWrite(HiSysEvent::Domain::USB, "PLUG_IN_OUT_HOST_MODE", HiSysEvent::EventType::BEHAVIOR, 270 "DEVICE_NAME", dev.GetName(), "DEVICE_PROTOCOL", dev.GetProtocol(), 271 "DEVICE_SUBCLASS", dev.GetSubclass(), "DEVICE_CLASS", dev.GetClass(), 272 "DEVICE_CLASS_DESCRIPTION", deviceUsageDes, "INTERFACE_CLASS_DESCRIPTION", extUsageDes, 273 "VENDOR_ID", dev.GetVendorId(), "PRODUCT_ID", dev.GetProductId(), 274 "VERSION", dev.GetVersion(), "EVENT_NAME", event); 275} 276} // namespace USB 277} // namespace OHOS 278