1 /*
2 * Copyright (c) 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
16 #include "string"
17 #include "securec.h"
18 #include "hilog_wrapper.h"
19 #include "edm_errors.h"
20 #include "usb_dev_subscriber.h"
21 namespace OHOS {
22 namespace ExternalDeviceManager {
23 using namespace std;
24 constexpr uint32_t MAX_DEV_ID_SIZE = 100;
25 constexpr uint32_t ACT_DEVUP = 0;
26 constexpr uint32_t ACT_DEVDOWN = 1;
27 constexpr uint32_t SHIFT_16 = 16;
28 constexpr uint32_t SHIFT_32 = 32;
29 constexpr uint32_t USB_DEV_DESC_SIZE = 0x12;
30 struct UsbDevDescLite {
31 uint8_t bLength;
32 uint8_t bDescriptorType;
33 uint16_t bcdUSB;
34 uint8_t bDeviceClass;
35 uint8_t bDeviceSubClass;
36 uint8_t bDeviceProtocol;
37 uint8_t bMaxPacketSize0;
38 uint16_t idVendor;
39 uint16_t idProduct;
40 } __attribute__((packed));
41
ToDeviceDesc(const UsbDev & usbDev,const UsbDevDescLite & desc)42 static string ToDeviceDesc(const UsbDev& usbDev, const UsbDevDescLite& desc)
43 {
44 char buffer[MAX_DEV_ID_SIZE];
45 auto ret = sprintf_s(buffer, sizeof(buffer), "USB&BUS_%02X&DEV_%02X&PID_%04X&VID_%04X&CLASS_%02X",\
46 usbDev.busNum, usbDev.devAddr, desc.idProduct, desc.idVendor, desc.bDeviceClass);
47 if (ret < 0) {
48 EDM_LOGE(MODULE_BUS_USB, "ToDeivceDesc sprintf_s error. ret = %{public}d", ret);
49 return string();
50 }
51 return string(buffer);
52 }
53
ToBusDeivceId(const UsbDev & usbDev)54 static uint32_t ToBusDeivceId(const UsbDev& usbDev)
55 {
56 uint32_t devId = (usbDev.busNum << SHIFT_16) + usbDev.devAddr;
57 return devId;
58 }
59
ToDdkDeviceId(const UsbDev & usbDev)60 static uint64_t ToDdkDeviceId(const UsbDev& usbDev)
61 {
62 return ((uint64_t)usbDev.busNum << SHIFT_32) + usbDev.devAddr;
63 }
64
65
Init(shared_ptr<IDevChangeCallback> callback,sptr<IUsbInterface> iusb,sptr<IUsbDdk> iUsbDdk)66 void UsbDevSubscriber::Init(shared_ptr<IDevChangeCallback> callback, sptr<IUsbInterface> iusb, sptr<IUsbDdk> iUsbDdk)
67 {
68 this->iusb_ = iusb;
69 this->callback_ = callback;
70 this->iUsbDdk_ = iUsbDdk;
71 };
72
GetInterfaceDescriptor(const UsbDev & usbDev,std::vector<UsbInterfaceDescriptor> & interfaceList)73 int32_t UsbDevSubscriber::GetInterfaceDescriptor(const UsbDev &usbDev,
74 std::vector<UsbInterfaceDescriptor> &interfaceList)
75 {
76 int32_t ret = EDM_NOK;
77 if (this->iusb_ == nullptr || this->iUsbDdk_ == nullptr) {
78 return EDM_ERR_INVALID_OBJECT;
79 }
80 uint8_t configIndex;
81 ret = this->iusb_->GetConfig(usbDev, configIndex);
82 if (ret != EDM_OK) {
83 EDM_LOGE(MODULE_BUS_USB, "GetConfig fail, ret = %{public}d", ret);
84 return ret;
85 }
86
87 uint64_t ddkDeviceId = ToDdkDeviceId(usbDev);
88 std::vector<uint8_t> descriptor;
89 ret = this->iUsbDdk_->GetConfigDescriptor(ddkDeviceId, configIndex, descriptor);
90 if (ret != EDM_OK) {
91 EDM_LOGE(MODULE_BUS_USB, "GetConfigDescriptor fail, ret = %{public}d", ret);
92 return ret;
93 }
94 UsbDdkConfigDescriptor *config = nullptr;
95 ret = ParseUsbConfigDescriptor(descriptor, &config);
96 if (ret != EDM_OK || config == nullptr) {
97 FreeUsbConfigDescriptor(config);
98 EDM_LOGE(MODULE_BUS_USB, "ParseUsbConfigDescriptor fail, ret = %{public}d", ret);
99 return ret;
100 }
101 if (config->interface == nullptr) {
102 FreeUsbConfigDescriptor(config);
103 EDM_LOGE(MODULE_BUS_USB, "UsbDdkInterface is null");
104 return EDM_ERR_INVALID_OBJECT;
105 }
106 for (uint8_t i = 0; i < config->configDescriptor.bNumInterfaces; i++) {
107 UsbDdkInterfaceDescriptor *interfaceDesc = config->interface[i].altsetting;
108 if (interfaceDesc == nullptr) {
109 FreeUsbConfigDescriptor(config);
110 EDM_LOGE(MODULE_BUS_USB, "UsbDdkInterfaceDescriptor is null");
111 return EDM_ERR_INVALID_OBJECT;
112 }
113 interfaceList.push_back(interfaceDesc->interfaceDescriptor);
114 }
115 FreeUsbConfigDescriptor(config);
116 return EDM_OK;
117 }
118
OnDeviceConnect(const UsbDev & usbDev)119 int32_t UsbDevSubscriber::OnDeviceConnect(const UsbDev &usbDev)
120 {
121 EDM_LOGD(MODULE_BUS_USB, "OnDeviceConnect enter");
122 int32_t ret = 0;
123 if (this->iusb_ == nullptr) {
124 return EDM_ERR_INVALID_OBJECT;
125 }
126 vector<uint8_t> descData;
127 ret = this->iusb_->GetDeviceDescriptor(usbDev, descData);
128 if (ret != 0) {
129 EDM_LOGE(MODULE_BUS_USB, "GetDeviceDescriptor fail, ret = %{public}d\n", ret);
130 return EDM_ERR_IO;
131 }
132 uint8_t *buffer = descData.data();
133 uint32_t length = descData.size();
134 if (length == 0) {
135 EDM_LOGE(MODULE_BUS_USB, "GetRawDescriptor failed len=%{public}d busNum:%{public}d devAddr:%{public}d",\
136 length, usbDev.busNum, usbDev.devAddr);
137 return EDM_ERR_USB_ERR;
138 }
139 UsbDevDescLite deviceDescriptor = *(reinterpret_cast<const UsbDevDescLite *>(buffer));
140 if (deviceDescriptor.bLength != USB_DEV_DESC_SIZE) {
141 EDM_LOGE(MODULE_BUS_USB, "UsbdDeviceDescriptor size error");
142 return EDM_ERR_USB_ERR;
143 }
144 string desc = ToDeviceDesc(usbDev, deviceDescriptor);
145 uint32_t busDevId = ToBusDeivceId(usbDev);
146 auto usbDevInfo = make_shared<UsbDeviceInfo>(busDevId, desc);
147
148 usbDevInfo->bcdUSB_ = deviceDescriptor.bcdUSB;
149 usbDevInfo->idProduct_ = deviceDescriptor.idProduct;
150 usbDevInfo->idVendor_ = deviceDescriptor.idVendor;
151 usbDevInfo->deviceClass_ = deviceDescriptor.bDeviceClass;
152
153 ret = GetInterfaceDescriptor(usbDev, usbDevInfo->interfaceDescList_);
154 if (ret != EDM_OK) {
155 EDM_LOGE(MODULE_BUS_USB, "GetInterfaceDescriptor fail, ret = %{public}d", ret);
156 return ret;
157 }
158
159 this->deviceInfos_[busDevId] = usbDevInfo;
160 if (this->callback_ != nullptr) {
161 this->callback_->OnDeviceAdd(usbDevInfo);
162 }
163 EDM_LOGD(MODULE_BUS_USB, "OnDeviceConnect:");
164 EDM_LOGD(MODULE_BUS_USB, "%{public}s", desc.c_str());
165 return EDM_OK;
166 };
167
OnDeviceDisconnect(const UsbDev & usbDev)168 int32_t UsbDevSubscriber::OnDeviceDisconnect(const UsbDev &usbDev)
169 {
170 EDM_LOGD(MODULE_BUS_USB, "OnDeviceDisconnect enter");
171 uint32_t busDevId = ToBusDeivceId(usbDev);
172 if (this->callback_ != nullptr) {
173 auto deviceInfo = this->deviceInfos_[busDevId];
174 if (deviceInfo != nullptr) {
175 this->callback_->OnDeviceRemove(deviceInfo);
176 } else {
177 EDM_LOGW(MODULE_BUS_USB, "no dev in map, busDevId=%{public}08X \n", busDevId);
178 }
179 }
180 this->deviceInfos_.erase(busDevId);
181 return 0;
182 }
183
DeviceEvent(const USBDeviceInfo & usbDevInfo)184 int32_t UsbDevSubscriber::DeviceEvent(const USBDeviceInfo &usbDevInfo)
185 {
186 EDM_LOGD(MODULE_BUS_USB, "DeviceEvent enter");
187 UsbDev usbDev = {usbDevInfo.busNum, usbDevInfo.devNum};
188 int32_t ret = 0;
189 if (usbDevInfo.status == ACT_DEVUP) {
190 ret = this->OnDeviceConnect(usbDev);
191 } else if (usbDevInfo.status == ACT_DEVDOWN) {
192 ret = this->OnDeviceDisconnect(usbDev);
193 } else {
194 EDM_LOGW(MODULE_BUS_USB, "status not support, %{public}d \n", usbDevInfo.status);
195 }
196 EDM_LOGD(MODULE_BUS_USB, "ret = %{public}d, %{public}s", ret, this->ToString().c_str());
197 return ret;
198 }
199
PortChangedEvent(const PortInfo & usbDevInfo)200 int32_t UsbDevSubscriber::PortChangedEvent(const PortInfo &usbDevInfo)
201 {
202 return 0;
203 }
204
ToString(void)205 string UsbDevSubscriber::ToString(void)
206 {
207 string str = "DeviceInfos: Device count:" + to_string(this->deviceInfos_.size()) + "\n";
208 int i = 0;
209 for (auto it = this->deviceInfos_.begin(); it != deviceInfos_.end(); it++) {
210 str += "[" +to_string(i++) + "]" + to_string(it->first) + "\n";
211 }
212 return str;
213 }
214 }
215 }