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 USB_DEV_DESC_SIZE = 0x12;
29 struct UsbDevDescLite {
30 uint8_t bLength;
31 uint8_t bDescriptorType;
32 uint16_t bcdUSB;
33 uint8_t bDeviceClass;
34 uint8_t bDeviceSubClass;
35 uint8_t bDeviceProtocol;
36 uint8_t bMaxPacketSize0;
37 uint16_t idVendor;
38 uint16_t idProduct;
39 } __attribute__((packed));
40
ToDeviceDesc(const UsbDev & usbDev,const UsbDevDescLite & desc)41 static string ToDeviceDesc(const UsbDev& usbDev, const UsbDevDescLite& desc)
42 {
43 char buffer[MAX_DEV_ID_SIZE];
44 auto ret = sprintf_s(buffer, sizeof(buffer), "USB&BUS_%02X&DEV_%02X&PID_%04X&VID_%04X&CLASS_%02X",\
45 usbDev.busNum, usbDev.devAddr, desc.idProduct, desc.idVendor, desc.bDeviceClass);
46 if (ret < 0) {
47 EDM_LOGE(MODULE_BUS_USB, "ToDeivceDesc sprintf_s error. ret = %{public}d", ret);
48 return string();
49 }
50 return string(buffer);
51 }
52
ToBusDeivceId(const UsbDev & usbDev)53 static uint32_t ToBusDeivceId(const UsbDev& usbDev)
54 {
55 uint32_t devId = (usbDev.busNum << SHIFT_16) + usbDev.devAddr;
56 return devId;
57 }
58
59
Init(shared_ptr<IDevChangeCallback> callback,sptr<IUsbInterface> iusb)60 void UsbDevSubscriber::Init(shared_ptr<IDevChangeCallback> callback, sptr<IUsbInterface> iusb)
61 {
62 this->iusb_ = iusb;
63 this->callback_ = callback;
64 };
65
OnDeviceConnect(const UsbDev & usbDev)66 int32_t UsbDevSubscriber::OnDeviceConnect(const UsbDev &usbDev)
67 {
68 int32_t ret = 0;
69 if (this->iusb_ == nullptr) {
70 return EDM_ERR_INVALID_OBJECT;
71 }
72 vector<uint8_t> descData;
73 ret = this->iusb_->GetDeviceDescriptor(usbDev, descData);
74 if (ret != 0) {
75 EDM_LOGE(MODULE_BUS_USB, "GetDeviceDescriptor fail, ret = %{public}d\n", ret);
76 return EDM_ERR_IO;
77 }
78 uint8_t *buffer = descData.data();
79 uint32_t length = descData.size();
80 if (length == 0) {
81 EDM_LOGE(MODULE_BUS_USB, "GetRawDescriptor failed len=%{public}d busNum:%{public}d devAddr:%{public}d",\
82 length, usbDev.busNum, usbDev.devAddr);
83 return EDM_ERR_USB_ERR;
84 }
85 UsbDevDescLite deviceDescriptor = *(reinterpret_cast<const UsbDevDescLite *>(buffer));
86 if (deviceDescriptor.bLength != USB_DEV_DESC_SIZE) {
87 EDM_LOGE(MODULE_BUS_USB, "UsbdDeviceDescriptor size error");
88 return EDM_ERR_USB_ERR;
89 }
90 string desc = ToDeviceDesc(usbDev, deviceDescriptor);
91 uint32_t busDevId = ToBusDeivceId(usbDev);
92 auto usbDevInfo = make_shared<UsbDeviceInfo>(busDevId, desc);
93
94 usbDevInfo->bcdUSB_ = deviceDescriptor.bcdUSB;
95 usbDevInfo->idProduct_ = deviceDescriptor.idProduct;
96 usbDevInfo->idVendor_ = deviceDescriptor.idVendor;
97 usbDevInfo->deviceClass_ = deviceDescriptor.bDeviceClass;
98
99 this->deviceInfos_[busDevId] = usbDevInfo;
100 if (this->callback_ != nullptr) {
101 this->callback_->OnDeviceAdd(usbDevInfo);
102 }
103 EDM_LOGD(MODULE_BUS_USB, "OnDeviceConnect:");
104 EDM_LOGD(MODULE_BUS_USB, "%{public}s", desc.c_str());
105 return EDM_OK;
106 };
107
OnDeviceDisconnect(const UsbDev & usbDev)108 int32_t UsbDevSubscriber::OnDeviceDisconnect(const UsbDev &usbDev)
109 {
110 uint32_t busDevId = ToBusDeivceId(usbDev);
111 if (this->callback_ != nullptr) {
112 auto deviceInfo = this->deviceInfos_[busDevId];
113 if (deviceInfo != nullptr) {
114 this->callback_->OnDeviceRemove(deviceInfo);
115 } else {
116 EDM_LOGW(MODULE_BUS_USB, "no dev in map, busDevId=%{public}08X \n", busDevId);
117 }
118 }
119 this->deviceInfos_.erase(busDevId);
120 return 0;
121 }
122
DeviceEvent(const USBDeviceInfo & usbDevInfo)123 int32_t UsbDevSubscriber::DeviceEvent(const USBDeviceInfo &usbDevInfo)
124 {
125 UsbDev usbDev = {usbDevInfo.busNum, usbDevInfo.devNum};
126 int32_t ret = 0;
127 if (usbDevInfo.status == ACT_DEVUP) {
128 ret = this->OnDeviceConnect(usbDev);
129 } else if (usbDevInfo.status == ACT_DEVDOWN) {
130 ret = this->OnDeviceDisconnect(usbDev);
131 } else {
132 EDM_LOGW(MODULE_BUS_USB, "status not support, %{public}d \n", usbDevInfo.status);
133 }
134 EDM_LOGD(MODULE_BUS_USB, "ret = %{public}d, %{public}s", ret, this->ToString().c_str());
135 return ret;
136 }
137
PortChangedEvent(const PortInfo & usbDevInfo)138 int32_t UsbDevSubscriber::PortChangedEvent(const PortInfo &usbDevInfo)
139 {
140 return 0;
141 }
142
ToString(void)143 string UsbDevSubscriber::ToString(void)
144 {
145 string str = "DeviceInfos: Device count:" + to_string(this->deviceInfos_.size()) + "\n";
146 int i = 0;
147 for (auto it = this->deviceInfos_.begin(); it != deviceInfos_.end(); it++) {
148 str += "[" +to_string(i++) + "]" + to_string(it->first) + "\n";
149 }
150 return str;
151 }
152 }
153 }