1 /*
2 * Copyright (c) 2024 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 "mtp/usb_event_subscriber.h"
17 #include <libmtp.h>
18 #include <unistd.h>
19 #include "mtp/mtp_device_monitor.h"
20 #include "storage_service_errno.h"
21 #include "storage_service_log.h"
22
23 namespace OHOS {
24 namespace StorageDaemon {
25 constexpr const char *BUS_NUM_KEY = "busNum";
26 constexpr const char *DEV_ADDRESS_KEY = "devAddress";
27 constexpr const char *DEV_VENDOR_ID_KEY = "vendorId";
28 constexpr const char *DEV_PRODUCT_ID_KEY = "productId";
29 constexpr const char *DEV_CLASS_KEY = "clazz";
30 constexpr int USB_CLASS_IMAGE = 6;
31 constexpr int USB_CLASS_VENDOR_SPEC = 255;
32 bool UsbEventSubscriber::isPtp_ = true;
33
UsbEventSubscriber(const EventFwk::CommonEventSubscribeInfo & info)34 UsbEventSubscriber::UsbEventSubscriber(const EventFwk::CommonEventSubscribeInfo &info)
35 : EventFwk::CommonEventSubscriber(info)
36 {}
37
38 std::shared_ptr<UsbEventSubscriber> usbEventSubscriber_ = nullptr;
SubscribeCommonEvent(void)39 void UsbEventSubscriber::SubscribeCommonEvent(void)
40 {
41 if (usbEventSubscriber_ == nullptr) {
42 EventFwk::MatchingSkills matchingSkills;
43 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USB_STATE);
44 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USB_PORT_CHANGED);
45 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USB_DEVICE_ATTACHED);
46 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USB_DEVICE_DETACHED);
47 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USB_ACCESSORY_ATTACHED);
48 matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USB_ACCESSORY_DETACHED);
49 EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
50 usbEventSubscriber_ = std::make_shared<UsbEventSubscriber>(subscribeInfo);
51 if (!EventFwk::CommonEventManager::SubscribeCommonEvent(usbEventSubscriber_)) {
52 usbEventSubscriber_ = nullptr;
53 LOGE("UsbEventSubscriber subscribe common event failed.");
54 }
55 }
56 }
57
OnReceiveEvent(const OHOS::EventFwk::CommonEventData & data)58 void UsbEventSubscriber::OnReceiveEvent(const OHOS::EventFwk::CommonEventData &data)
59 {
60 LOGI("UsbEventSubscriber::OnReceiveEvent.");
61 auto want = data.GetWant();
62 std::string action = want.GetAction();
63 if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USB_STATE) {
64 LOGI("OnReceiveEvent COMMON_EVENT_USB_STATE, data=%{public}s", data.GetData().c_str());
65 }
66 if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USB_PORT_CHANGED) {
67 LOGI("OnReceiveEvent COMMON_EVENT_USB_PORT_CHANGED, data=%{public}s", data.GetData().c_str());
68 }
69 if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USB_ACCESSORY_ATTACHED) {
70 LOGI("OnReceiveEvent COMMON_EVENT_USB_ACCESSORY_ATTACHED, data=%{public}s", data.GetData().c_str());
71 }
72 if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USB_ACCESSORY_DETACHED) {
73 LOGI("OnReceiveEvent COMMON_EVENT_USB_ACCESSORY_DETACHED, data=%{public}s", data.GetData().c_str());
74 }
75 if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USB_DEVICE_ATTACHED) {
76 std::string usbInfo = data.GetData();
77 LOGI("OnReceiveEvent COMMON_EVENT_USB_DEVICE_ATTACHED, data=%{public}s", usbInfo.c_str());
78 #ifdef SUPPORT_OPEN_SOURCE_MTP_DEVICE
79 if (IsMTPDevice(usbInfo)) {
80 MtpDeviceMonitor::GetInstance().MountMtpDeviceByBroadcast();
81 }
82 #endif
83 }
84 if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USB_DEVICE_DETACHED) {
85 std::string usbInfo = data.GetData();
86 LOGI("OnReceiveEvent COMMON_EVENT_USB_DEVICE_DETACHED, data=%{public}s", data.GetData().c_str());
87 #ifdef SUPPORT_OPEN_SOURCE_MTP_DEVICE
88 if (IsMTPDevice(usbInfo)) {
89 uint8_t devNum = 0;
90 uint32_t busLoc = 0;
91 GetValueFromUsbDataInfo(data.GetData(), devNum, busLoc);
92 MtpDeviceMonitor::GetInstance().UmountDetachedMtpDevice(devNum, busLoc);
93 }
94 #endif
95 }
96 }
97
GetValueFromUsbDataInfo(const std::string & jsonStr,uint8_t & devNum,uint32_t & busLoc)98 void UsbEventSubscriber::GetValueFromUsbDataInfo(const std::string &jsonStr, uint8_t &devNum, uint32_t &busLoc)
99 {
100 cJSON *usbJson = cJSON_Parse(jsonStr.c_str());
101 if (usbJson == nullptr) {
102 LOGE("GetValueFromUsbDataInfo failed, parse json object is nullptr.");
103 return;
104 }
105 cJSON *busLocObj = cJSON_GetObjectItemCaseSensitive(usbJson, DEV_ADDRESS_KEY);
106 if (busLocObj != nullptr && cJSON_IsNumber(busLocObj)) {
107 devNum = static_cast<uint8_t>(busLocObj->valueint);
108 }
109 cJSON *devNumObj = cJSON_GetObjectItemCaseSensitive(usbJson, BUS_NUM_KEY);
110 if (devNumObj != nullptr && cJSON_IsNumber(devNumObj)) {
111 busLoc = static_cast<uint32_t>(devNumObj->valueint);
112 }
113 cJSON_Delete(usbJson);
114 }
115
ToLowerString(const char * str)116 std::string UsbEventSubscriber::ToLowerString(const char* str)
117 {
118 if (str == nullptr) {
119 return "";
120 }
121 std::string lowerStr(str);
122 std::transform(lowerStr.begin(), lowerStr.end(), lowerStr.begin(),
123 [](unsigned char c) { return std::tolower(c); });
124 return lowerStr;
125 }
126
CheckMtpInterface(const cJSON * iface)127 bool UsbEventSubscriber::CheckMtpInterface(const cJSON* iface)
128 {
129 cJSON* clazz = cJSON_GetObjectItemCaseSensitive(iface, "clazz");
130 if (clazz != nullptr && cJSON_IsNumber(clazz) && clazz->valueint) {
131 const int ifaceClazz = clazz->valueint;
132 if (ifaceClazz == USB_CLASS_IMAGE || ifaceClazz == USB_CLASS_VENDOR_SPEC) {
133 return true;
134 }
135 }
136
137 cJSON* name = cJSON_GetObjectItemCaseSensitive(iface, "name");
138 if (name != nullptr && cJSON_IsString(name) && name->valuestring) {
139 const std::string ifaceName = ToLowerString(name->valuestring);
140 if (ifaceName.find("mtp") != std::string::npos) {
141 isPtp_ = false;
142 return true;
143 }
144 if (ifaceName.find("ptp") != std::string::npos) {
145 isPtp_ = true;
146 return true;
147 }
148 }
149 return false;
150 }
151
CheckAllInterfaces(const cJSON * configs)152 bool UsbEventSubscriber::CheckAllInterfaces(const cJSON* configs)
153 {
154 if (configs == nullptr || !cJSON_IsArray(configs)) {
155 return false;
156 }
157
158 cJSON* config = nullptr;
159 cJSON_ArrayForEach(config, configs) {
160 cJSON* name = cJSON_GetObjectItemCaseSensitive(config, "name");
161 if (name != nullptr && cJSON_IsString(name) && name->valuestring) {
162 const std::string configName = ToLowerString(name->valuestring);
163 if (configName.find("mtp") != std::string::npos) {
164 isPtp_ = false;
165 return true;
166 }
167 if (configName.find("ptp") != std::string::npos) {
168 isPtp_ = true;
169 return true;
170 }
171 }
172 cJSON* interfaces = cJSON_GetObjectItemCaseSensitive(config, "interfaces");
173 if (interfaces == nullptr || !cJSON_IsArray(interfaces)) {
174 continue;
175 }
176 cJSON* iface = nullptr;
177 cJSON_ArrayForEach(iface, interfaces) {
178 if (CheckMtpInterface(iface)) {
179 return true;
180 }
181 }
182 }
183 return false;
184 }
185
IsMTPDevice(const std::string & usbInfo)186 bool UsbEventSubscriber::IsMTPDevice(const std::string &usbInfo)
187 {
188 cJSON *usbJson = cJSON_Parse(usbInfo.c_str());
189 if (usbJson == nullptr) {
190 LOGE("IsMTPDevice failed, parse json object is nullptr.");
191 return false;
192 }
193
194 cJSON* productName = cJSON_GetObjectItemCaseSensitive(usbJson, "productName");
195 if (productName && cJSON_IsString(productName) && productName->valuestring) {
196 std::string lowerName = ToLowerString(productName->valuestring);
197 if ((lowerName.find("mtp") != std::string::npos || lowerName.find("ptp") != std::string::npos)) {
198 cJSON_Delete(usbJson);
199 return true;
200 }
201 }
202
203 cJSON* configs = cJSON_GetObjectItemCaseSensitive(usbJson, "configs");
204 if (CheckAllInterfaces(configs)) {
205 cJSON_Delete(usbJson);
206 return true;
207 }
208
209 cJSON *classObj = cJSON_GetObjectItemCaseSensitive(usbJson, DEV_CLASS_KEY);
210 if (classObj == nullptr || !cJSON_IsNumber(classObj)) {
211 LOGE("parse deviceClass failed.");
212 cJSON_Delete(usbJson);
213 return false;
214 }
215 uint8_t deviceClass = static_cast<uint8_t>(classObj->valueint);
216 cJSON *vendorObj = cJSON_GetObjectItemCaseSensitive(usbJson, DEV_VENDOR_ID_KEY);
217 if (vendorObj == nullptr || !cJSON_IsNumber(vendorObj)) {
218 LOGE("parse vendorObj failed.");
219 cJSON_Delete(usbJson);
220 return false;
221 }
222 uint16_t idVendor = static_cast<uint16_t>(vendorObj->valueint);
223 cJSON *productObj = cJSON_GetObjectItemCaseSensitive(usbJson, DEV_PRODUCT_ID_KEY);
224 if (productObj == nullptr || !cJSON_IsNumber(productObj)) {
225 LOGE("parse productObj failed.");
226 cJSON_Delete(usbJson);
227 return false;
228 }
229 uint16_t idProduct = static_cast<uint16_t>(productObj->valueint);
230 cJSON_Delete(usbJson);
231 if (LIBMTP_check_is_mtp_device(deviceClass, idVendor, idProduct)) {
232 LOGE("this is mtp device.");
233 return true;
234 }
235 LOGE("this is not mtp device.");
236 return false;
237 }
238
IsPtpMode()239 bool UsbEventSubscriber::IsPtpMode()
240 {
241 LOGI("PTP mode status: %{public}d", isPtp_);
242 return isPtp_;
243 }
244 } // namespace StorageDaemon
245 } // namespace OHOS