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