1 /*
2 * Copyright (c) 2023-2025 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 "string"
17 #include "securec.h"
18 #include "hilog_wrapper.h"
19 #include "edm_errors.h"
20 #include "usb_dev_subscriber.h"
21 #include <cwchar>
22 #include <algorithm>
23 #include "driver_report_sys_event.h"
24 namespace OHOS {
25 namespace ExternalDeviceManager {
26 using namespace std;
27 constexpr uint32_t MAX_DEV_ID_SIZE = 100;
28 constexpr uint32_t ACT_DEVUP = 0;
29 constexpr uint32_t ACT_DEVDOWN = 1;
30 constexpr uint32_t SHIFT_16 = 16;
31 constexpr uint32_t SHIFT_32 = 32;
32 constexpr uint32_t USB_DEV_DESC_SIZE = 0x12;
33 constexpr int32_t DESCRIPTOR_TYPE_STRING = 3;
34 constexpr int32_t DESCRIPTOR_VALUE_START_OFFSET = 2;
35 constexpr int32_t HALF = 2;
36 constexpr uint8_t USB_CLASS_HUB = 0x09;
37
ToDeviceDesc(const UsbDev & usbDev,const UsbDevDescLite & desc)38 static string ToDeviceDesc(const UsbDev& usbDev, const UsbDevDescLite& desc)
39 {
40 char buffer[MAX_DEV_ID_SIZE];
41 auto ret = sprintf_s(buffer, sizeof(buffer), "USB&BUS_%02X&DEV_%02X&PID_%04X&VID_%04X&CLASS_%02X",\
42 usbDev.busNum, usbDev.devAddr, desc.idProduct, desc.idVendor, desc.bDeviceClass);
43 if (ret < 0) {
44 EDM_LOGE(MODULE_BUS_USB, "ToDeivceDesc sprintf_s error. ret = %{public}d", ret);
45 return string();
46 }
47 return string(buffer);
48 }
49
ToBusDeivceId(const UsbDev & usbDev)50 static uint32_t ToBusDeivceId(const UsbDev& usbDev)
51 {
52 uint32_t devId = (usbDev.busNum << SHIFT_16) + usbDev.devAddr;
53 return devId;
54 }
55
ToDdkDeviceId(const UsbDev & usbDev)56 static uint64_t ToDdkDeviceId(const UsbDev& usbDev)
57 {
58 return ((uint64_t)usbDev.busNum << SHIFT_32) + usbDev.devAddr;
59 }
60
ToExtDevId(const UsbDev & usbDev)61 static uint64_t ToExtDevId(const UsbDev& usbDev)
62 {
63 union DevInfo {
64 uint64_t deviceId;
65 struct {
66 BusType busType;
67 uint32_t busDeviceId;
68 } devBusInfo;
69 } devInfo;
70
71 devInfo.devBusInfo.busType = BusType::BUS_TYPE_USB;
72 devInfo.devBusInfo.busDeviceId = ToBusDeivceId(usbDev);
73
74 return devInfo.deviceId;
75 }
76
77 #ifdef EXTDEVMGR_USB_PASS_THROUGH
Init(shared_ptr<IDevChangeCallback> callback,sptr<IUsbHostInterface> iusb,sptr<V1_1::IUsbDdk> iUsbDdk)78 void UsbDevSubscriber::Init(shared_ptr<IDevChangeCallback> callback, sptr<IUsbHostInterface> iusb,
79 sptr<V1_1::IUsbDdk> iUsbDdk)
80 {
81 this->iusb_ = iusb;
82 this->callback_ = callback;
83 this->iUsbDdk_ = iUsbDdk;
84 };
85 #else
Init(shared_ptr<IDevChangeCallback> callback,sptr<IUsbInterface> iusb,sptr<V1_1::IUsbDdk> iUsbDdk)86 void UsbDevSubscriber::Init(shared_ptr<IDevChangeCallback> callback, sptr<IUsbInterface> iusb,
87 sptr<V1_1::IUsbDdk> iUsbDdk)
88 {
89 this->iusb_ = iusb;
90 this->callback_ = callback;
91 this->iUsbDdk_ = iUsbDdk;
92 };
93 #endif // EXTDEVMGR_USB_PASS_THROUGH
94
GetInterfaceDescriptor(const UsbDev & usbDev,std::vector<UsbInterfaceDescriptor> & interfaceList)95 int32_t UsbDevSubscriber::GetInterfaceDescriptor(const UsbDev &usbDev,
96 std::vector<UsbInterfaceDescriptor> &interfaceList)
97 {
98 int32_t ret = EDM_NOK;
99 if (this->iusb_ == nullptr || this->iUsbDdk_ == nullptr) {
100 return EDM_ERR_INVALID_OBJECT;
101 }
102 uint8_t configIndex;
103 ret = this->iusb_->GetConfig(usbDev, configIndex);
104 if (ret != EDM_OK) {
105 EDM_LOGE(MODULE_BUS_USB, "GetConfig fail, ret = %{public}d", ret);
106 return ret;
107 }
108
109 uint64_t ddkDeviceId = ToDdkDeviceId(usbDev);
110 std::vector<uint8_t> descriptor;
111 ret = this->iUsbDdk_->GetConfigDescriptor(ddkDeviceId, configIndex, descriptor);
112 if (ret != EDM_OK) {
113 EDM_LOGE(MODULE_BUS_USB, "GetConfigDescriptor fail, ret = %{public}d", ret);
114 return ret;
115 }
116 UsbDdkConfigDescriptor *config = nullptr;
117 ret = ParseUsbConfigDescriptor(descriptor, &config);
118 if (ret != EDM_OK || config == nullptr) {
119 FreeUsbConfigDescriptor(config);
120 EDM_LOGE(MODULE_BUS_USB, "ParseUsbConfigDescriptor fail, ret = %{public}d", ret);
121 return ret;
122 }
123 if (config->interface == nullptr) {
124 FreeUsbConfigDescriptor(config);
125 EDM_LOGE(MODULE_BUS_USB, "UsbDdkInterface is null");
126 return EDM_ERR_INVALID_OBJECT;
127 }
128 for (uint8_t i = 0; i < config->configDescriptor.bNumInterfaces; i++) {
129 UsbDdkInterfaceDescriptor *interfaceDesc = config->interface[i].altsetting;
130 if (interfaceDesc == nullptr) {
131 FreeUsbConfigDescriptor(config);
132 EDM_LOGE(MODULE_BUS_USB, "UsbDdkInterfaceDescriptor is null");
133 return EDM_ERR_INVALID_OBJECT;
134 }
135 interfaceList.push_back(interfaceDesc->interfaceDescriptor);
136 }
137 FreeUsbConfigDescriptor(config);
138 return EDM_OK;
139 }
140
GetUsbDeviceDescriptor(const UsbDev & usbDev,UsbDevDescLite & deviceDescriptor)141 int32_t UsbDevSubscriber::GetUsbDeviceDescriptor(const UsbDev &usbDev, UsbDevDescLite &deviceDescriptor)
142 {
143 vector<uint8_t> descData;
144 int32_t ret = iusb_->GetDeviceDescriptor(usbDev, descData);
145 if (ret != EDM_OK || descData.empty()) {
146 EDM_LOGE(MODULE_BUS_USB, "GetDeviceDescriptor failed, ret = %{public}d", ret);
147 return EDM_ERR_IO;
148 }
149 deviceDescriptor = *(reinterpret_cast<const UsbDevDescLite *>(descData.data()));
150 if (deviceDescriptor.bLength != USB_DEV_DESC_SIZE) {
151 EDM_LOGE(MODULE_BUS_USB, "UsbdDeviceDescriptor size error");
152 return EDM_ERR_USB_ERR;
153 }
154 return EDM_OK;
155 }
156
OnDeviceConnect(const UsbDev & usbDev)157 int32_t UsbDevSubscriber::OnDeviceConnect(const UsbDev &usbDev)
158 {
159 std::shared_ptr<ExtDevEvent> extDevEvent = std::make_shared<ExtDevEvent>(__func__, GET_DEVICE_INFO,
160 ToExtDevId(usbDev));
161 int32_t ret = 0;
162 if (this->iusb_ == nullptr) {
163 return EDM_ERR_INVALID_OBJECT;
164 }
165 ret = this->iusb_->OpenDevice(usbDev);
166 if (ret != EDM_OK) {
167 EDM_LOGE(MODULE_BUS_USB, "OpenDevice failed, ret = %{public}d", ret);
168 ExtDevReportSysEvent::ReportExternalDeviceEvent(extDevEvent,
169 ExtDevReportSysEvent::EventErrCode::OPEN_DEVICE_FAILED);
170 return EDM_ERR_IO;
171 }
172
173 UsbDevDescLite deviceDescriptor;
174 ret = GetUsbDeviceDescriptor(usbDev, deviceDescriptor);
175 if (ret != EDM_OK) {
176 (void)this->iusb_->CloseDevice(usbDev);
177 ExtDevReportSysEvent::ReportExternalDeviceEvent(extDevEvent,
178 (ret == EDM_ERR_USB_ERR) ?
179 ExtDevReportSysEvent::EventErrCode::DEVICE_DESCRIPTOR_LENGTH_INVALID :
180 ExtDevReportSysEvent::EventErrCode::GET_DEVICE_DESCRIPTOR_FAILED);
181 return ret;
182 }
183
184 if (deviceDescriptor.bDeviceClass == USB_CLASS_HUB) {
185 EDM_LOGW(MODULE_BUS_USB, "USB device class is HUB, not supported");
186 (void)this->iusb_->CloseDevice(usbDev);
187 return EDM_OK;
188 }
189
190 auto usbDevInfo = make_shared<UsbDeviceInfo>(ToBusDeivceId(usbDev), ToDeviceDesc(usbDev, deviceDescriptor));
191 SetUsbDevInfoValue(deviceDescriptor, usbDevInfo, GetDevStringVal(usbDev, deviceDescriptor.iSerialNumber));
192 ExtDevReportSysEvent::ParseToExtDevEvent(usbDevInfo, extDevEvent);
193 ret = GetInterfaceDescriptor(usbDev, usbDevInfo->interfaceDescList_);
194 if (ret != EDM_OK) {
195 EDM_LOGE(MODULE_BUS_USB, "GetInterfaceDescriptor fail, ret = %{public}d", ret);
196 (void)this->iusb_->CloseDevice(usbDev);
197 ExtDevReportSysEvent::ReportExternalDeviceEvent(extDevEvent,
198 ExtDevReportSysEvent::EventErrCode::GET_INTERFACE_DESCRIPTOR_FAILED);
199 return ret;
200 }
201 ExtDevReportSysEvent::ReportExternalDeviceEvent(extDevEvent, ExtDevReportSysEvent::EventErrCode::SUCCESS);
202 (void)this->iusb_->CloseDevice(usbDev);
203 if (this->callback_ != nullptr) {
204 this->callback_->OnDeviceAdd(usbDevInfo);
205 }
206 return EDM_OK;
207 };
208
OnDeviceDisconnect(const UsbDev & usbDev)209 int32_t UsbDevSubscriber::OnDeviceDisconnect(const UsbDev &usbDev)
210 {
211 EDM_LOGD(MODULE_BUS_USB, "OnDeviceDisconnect enter");
212 std::string interfaceName = std::string(__func__);
213 if (this->callback_ != nullptr) {
214 uint32_t busDevId = ToBusDeivceId(usbDev);
215 auto deviceInfo = make_shared<UsbDeviceInfo>(busDevId);
216 if (deviceInfo != nullptr) {
217 this->callback_->OnDeviceRemove(deviceInfo);
218 } else {
219 EDM_LOGE(MODULE_BUS_USB, "deviceInfo is nullptr");
220 }
221 }
222 return 0;
223 }
224
DeviceEvent(const USBDeviceInfo & usbDevInfo)225 int32_t UsbDevSubscriber::DeviceEvent(const USBDeviceInfo &usbDevInfo)
226 {
227 EDM_LOGD(MODULE_BUS_USB, "DeviceEvent enter");
228 UsbDev usbDev = {usbDevInfo.busNum, usbDevInfo.devNum};
229 int32_t ret = 0;
230 if (usbDevInfo.status == ACT_DEVUP) {
231 ret = this->OnDeviceConnect(usbDev);
232 } else if (usbDevInfo.status == ACT_DEVDOWN) {
233 ret = this->OnDeviceDisconnect(usbDev);
234 } else {
235 EDM_LOGW(MODULE_BUS_USB, "status not support, %{public}d \n", usbDevInfo.status);
236 }
237 return ret;
238 }
239
PortChangedEvent(const PortInfo & usbDevInfo)240 int32_t UsbDevSubscriber::PortChangedEvent(const PortInfo &usbDevInfo)
241 {
242 return 0;
243 }
244
GetDevStringVal(const UsbDev & usbDev,uint8_t idx)245 std::string UsbDevSubscriber::GetDevStringVal(const UsbDev &usbDev, uint8_t idx)
246 {
247 std::string strDesc = " ";
248 std::vector<uint8_t> serial;
249
250 if (idx == 0) {
251 return strDesc;
252 }
253
254 auto ret = this->iusb_->GetStringDescriptor(usbDev, idx, serial);
255 if (ret != EDM_OK) {
256 EDM_LOGE(MODULE_BUS_USB, "GetStringDescriptor failed, ret = %{public}d", ret);
257 return strDesc;
258 }
259
260 size_t length = serial.size();
261 if ((length < DESCRIPTOR_VALUE_START_OFFSET) || (serial[1] != DESCRIPTOR_TYPE_STRING)) {
262 EDM_LOGE(MODULE_BUS_USB, "type or length error, len:%{public}zu", length);
263 return strDesc;
264 }
265
266 uint16_t *tbuf = new (std::nothrow) uint16_t[length + 1]();
267 if (tbuf == nullptr) {
268 EDM_LOGE(MODULE_BUS_USB, "new failed");
269 return strDesc;
270 }
271
272 for (uint32_t i = 0; i < length - DESCRIPTOR_VALUE_START_OFFSET; ++i) {
273 tbuf[i] = serial[i + DESCRIPTOR_VALUE_START_OFFSET];
274 }
275 size_t bufLen = (length - DESCRIPTOR_VALUE_START_OFFSET) / HALF;
276 size_t wstrLen = wcslen((wchar_t*)tbuf) <= bufLen ? wcslen((wchar_t*)tbuf) : bufLen;
277 std::wstring wstr(reinterpret_cast<wchar_t *>(tbuf), wstrLen);
278 strDesc = std::string(wstr.begin(), wstr.end());
279 EDM_LOGI(MODULE_BUS_USB, "getString idx:%{public}d length:%{public}zu, str: %{public}s",
280 idx, strDesc.length(), strDesc.c_str());
281 delete[] tbuf;
282 return strDesc;
283 }
284
SetUsbDevInfoValue(const UsbDevDescLite & deviceDescriptor,shared_ptr<UsbDeviceInfo> & usbDevInfo,std::string snNum)285 void UsbDevSubscriber::SetUsbDevInfoValue(const UsbDevDescLite &deviceDescriptor,
286 shared_ptr<UsbDeviceInfo> &usbDevInfo, std::string snNum)
287 {
288 usbDevInfo->bcdUSB_ = deviceDescriptor.bcdUSB;
289 usbDevInfo->idProduct_ = deviceDescriptor.idProduct;
290 usbDevInfo->idVendor_ = deviceDescriptor.idVendor;
291 usbDevInfo->deviceClass_ = deviceDescriptor.bDeviceClass;
292 usbDevInfo->deviceSubClass_ = deviceDescriptor.bDeviceSubClass;
293 usbDevInfo->deviceProtocol_ = deviceDescriptor.bDeviceProtocol;
294 usbDevInfo->snNum_ = snNum;
295 }
296 }
297 }