• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }