1 /*
2  * Copyright (C) 2022 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 #define MLOG_TAG "MtpOperation"
16 #include "mtp_operation.h"
17 #include <algorithm>
18 #include "header_data.h"
19 #include "media_log.h"
20 #include "media_mtp_utils.h"
21 #include "mtp_constants.h"
22 #include "mtp_global.h"
23 #include "mtp_packet.h"
24 #include "mtp_packet_tools.h"
25 #include "mtp_operation_context.h"
26 #include "mtp_operation_utils.h"
27 #include "mtp_storage_manager.h"
28 #include "packet_payload_factory.h"
29 #include "payload_data/get_device_info_data.h"
30 #include "payload_data.h"
31 #include "payload_data/send_object_info_data.h"
32 #include "payload_data/set_object_prop_value_data.h"
33 #include "storage.h"
34 
35 using namespace std;
36 namespace OHOS {
37 namespace Media {
MtpOperation(void)38 MtpOperation::MtpOperation(void)
39 {
40     Init();
41 }
42 
Init()43 void MtpOperation::Init()
44 {
45     mtpContextPtr_ = make_shared<MtpOperationContext>();
46     mtpContextPtr_->indata = false;
47 
48     mtpDriver_ = make_shared<MtpDriver>();
49     mtpContextPtr_->mtpDriver = mtpDriver_;
50 
51     requestPacketPtr_ = make_shared<MtpPacket>(mtpContextPtr_, mtpDriver_);
52     dataPacketPtr_ = make_shared<MtpPacket>(mtpContextPtr_, mtpDriver_);
53     responsePacketPtr_ = make_shared<MtpPacket>(mtpContextPtr_, mtpDriver_);
54 
55     operationUtils_ = make_shared<MtpOperationUtils>(mtpContextPtr_);
56     responseCode_ = MTP_UNDEFINED_CODE;
57 }
58 
Execute()59 void MtpOperation::Execute()
60 {
61     int errorCode;
62     ResetOperation();
63     ReceiveRequestPacket(errorCode);
64     if (errorCode != MTP_SUCCESS) {
65         SendMakeResponsePacket(errorCode);
66         MEDIA_ERR_LOG("MtpOperation::Execute Out ReceiveRequestPacket fail err: %{public}d", errorCode);
67         return;
68     }
69 
70     DealRequest(mtpContextPtr_->operationCode, errorCode);
71     if (errorCode != MTP_SUCCESS) {
72         SendMakeResponsePacket(errorCode);
73         MEDIA_ERR_LOG("MtpOperation::Execute Out DealRequest fail err: %{public}d", errorCode);
74         return;
75     }
76 
77     if (MtpPacket::IsNeedDataPhase(mtpContextPtr_->operationCode)) {
78         if (MtpPacket::IsI2R(mtpContextPtr_->operationCode)) {
79             ReceiveI2Rdata(errorCode);
80         } else {
81             SendR2Idata(errorCode);
82         }
83     }
84     if (errorCode == MTP_ERROR_TRANSFER_CANCELLED) {
85         MEDIA_INFO_LOG("File transfer canceled");
86         return;
87     }
88 
89     SendMakeResponsePacket(errorCode);
90 }
91 
ReceiveRequestPacket(int & errorCode)92 void MtpOperation::ReceiveRequestPacket(int &errorCode)
93 {
94     shared_ptr<HeaderData> headerData = make_shared<HeaderData>(mtpContextPtr_);
95     requestPacketPtr_->Init(headerData);
96     errorCode = requestPacketPtr_->Read();
97     if (errorCode != MTP_SUCCESS) {
98         MEDIA_ERR_LOG("requestPacket Read fail err: %{public}d", errorCode);
99         return;
100     }
101     errorCode = requestPacketPtr_->Parser();
102     if (errorCode != MTP_SUCCESS) {
103         MEDIA_ERR_LOG("requestPacket Parser fail err: %{public}d", errorCode);
104         return;
105     }
106 }
107 
SendMakeResponsePacket(int & errorCode)108 void MtpOperation::SendMakeResponsePacket(int &errorCode)
109 {
110     CHECK_AND_RETURN_LOG(responsePacketPtr_ != nullptr, "responsePacketPtr_ is null");
111     responsePacketPtr_->Reset();
112     CHECK_AND_RETURN_LOG(mtpContextPtr_ != nullptr, "mtpContextPtr_ is null");
113     GetPayloadData(mtpContextPtr_, dataPayloadData_, RESPONSE_CONTAINER_TYPE, errorCode);
114     if (mtpContextPtr_->operationCode != 0) {
115         MEDIA_INFO_LOG("operation = [0x%{public}x : %{public}s ]", mtpContextPtr_->operationCode,
116             MtpPacketTool::GetOperationName(mtpContextPtr_->operationCode).c_str());
117     }
118     shared_ptr<HeaderData> responseHeaderData = make_shared<HeaderData>(
119         RESPONSE_CONTAINER_TYPE, responseCode_, mtpContextPtr_->transactionID);
120 
121     responsePacketPtr_->Init(responseHeaderData, dataPayloadData_);
122     errorCode = responsePacketPtr_->Maker(false);
123     if (errorCode != MTP_SUCCESS) {
124         MEDIA_ERR_LOG("responsePacket Maker fail err: %{public}d", errorCode);
125         return;
126     }
127     errorCode = responsePacketPtr_->Write();
128     if (errorCode != MTP_SUCCESS) {
129         MEDIA_ERR_LOG("responsePacket Write fail err: %{public}d", errorCode);
130         return;
131     }
132 }
133 
SendObjectData(int & errorCode)134 void MtpOperation::SendObjectData(int &errorCode)
135 {
136     errorCode = operationUtils_->GetObjectDataDeal();
137 }
138 
RecevieObjectData(int & errorCode)139 void MtpOperation::RecevieObjectData(int &errorCode)
140 {
141     errorCode = operationUtils_->DoRecevieSendObject();
142 }
143 
ReceiveI2Rdata(int & errorCode)144 void MtpOperation::ReceiveI2Rdata(int &errorCode)
145 {
146     if (mtpContextPtr_->operationCode == MTP_OPERATION_SEND_OBJECT_CODE) {
147         MEDIA_INFO_LOG("ReceiveI2Rdata RecevieObjectData");
148         RecevieObjectData(errorCode);
149         return;
150     }
151     mtpContextPtr_->indata = true;
152 
153     errorCode = dataPacketPtr_->Read();
154     if (errorCode != MTP_SUCCESS) {
155         MEDIA_ERR_LOG("dataPacket Read fail err: %{public}d", errorCode);
156         return;
157     }
158     errorCode = dataPacketPtr_->Parser();
159     if (errorCode != MTP_SUCCESS) {
160         MEDIA_ERR_LOG("dataPacket Parser fail err: %{public}d", errorCode);
161         return;
162     }
163 
164     if (mtpContextPtr_->operationCode == MTP_OPERATION_SET_OBJECT_PROP_VALUE_CODE) {
165         MEDIA_INFO_LOG("ReceiveI2Rdata DoSetObjectPropValue");
166         operationUtils_->DoSetObjectPropValue(errorCode);
167     }
168 }
169 
SendR2Idata(int & errorCode)170 void MtpOperation::SendR2Idata(int &errorCode)
171 {
172     if (mtpContextPtr_->operationCode == MTP_OPERATION_GET_OBJECT_CODE) {
173         SendObjectData(errorCode);
174         return;
175     }
176 
177     responseCode_ = GetPayloadData(mtpContextPtr_, dataPayloadData_, DATA_CONTAINER_TYPE, errorCode);
178     MEDIA_INFO_LOG("operation = [0x%{public}x : %{public}s ]", mtpContextPtr_->operationCode,
179         MtpPacketTool::GetOperationName(mtpContextPtr_->operationCode).c_str());
180     if (errorCode != MTP_SUCCESS) {
181         MEDIA_ERR_LOG("GetPayloadData fail err: %{public}d", errorCode);
182         return;
183     }
184     shared_ptr<HeaderData> dataHeaderData = make_shared<HeaderData>(
185         DATA_CONTAINER_TYPE, mtpContextPtr_->operationCode, mtpContextPtr_->transactionID);
186     dataPacketPtr_->Init(dataHeaderData, dataPayloadData_);
187     errorCode = dataPacketPtr_->Maker(true);
188     if (errorCode != MTP_SUCCESS) {
189         MEDIA_ERR_LOG("dataPacket Maker fail err: %{public}d", errorCode);
190         return;
191     }
192     errorCode = dataPacketPtr_->Write();
193     if (errorCode != MTP_SUCCESS) {
194         MEDIA_ERR_LOG("dataPacket Write fail err: %{public}d", errorCode);
195         return;
196     }
197 }
198 
DealRequest(uint16_t operationCode,int & errorCode)199 void MtpOperation::DealRequest(uint16_t operationCode, int &errorCode)
200 {
201     switch (operationCode) {
202         case MTP_OPERATION_OPEN_SESSION_CODE:
203             if (!mtpContextPtr_->sessionOpen) {
204                 mtpContextPtr_->sessionID = mtpContextPtr_->tempSessionID;
205                 errorCode = MTP_SUCCESS;
206             } else {
207                 errorCode = MTP_ERROR_SESSION_ALREADY_OPEN;
208             }
209             break;
210         default:
211             errorCode = MTP_SUCCESS;
212             break;
213     }
214 }
215 
GetPayloadData(shared_ptr<MtpOperationContext> & context,shared_ptr<PayloadData> & data,uint16_t containerType,int & errorCode)216 uint16_t MtpOperation::GetPayloadData(shared_ptr<MtpOperationContext> &context, shared_ptr<PayloadData> &data,
217     uint16_t containerType, int &errorCode)
218 {
219     responseCode_ = MTP_UNDEFINED_CODE;
220     switch (context->operationCode) {
221         case MTP_OPERATION_GET_DEVICE_INFO_CODE:
222             responseCode_ = operationUtils_->GetDeviceInfo(data, containerType, errorCode);
223             break;
224         case MTP_OPERATION_OPEN_SESSION_CODE:
225             responseCode_ = operationUtils_->GetOpenSession(data, errorCode);
226             break;
227         case MTP_OPERATION_SET_DEVICE_PROP_VALUE_CODE:
228             responseCode_ = operationUtils_->SetDevicePropValueResp(data);
229             break;
230         default:
231             responseCode_ = GetPayloadDataSub(context, data, containerType, errorCode);
232             break;
233     }
234     return responseCode_;
235 }
236 
GetPayloadDataSub(shared_ptr<MtpOperationContext> & context,shared_ptr<PayloadData> & data,uint16_t containerType,int & errorCode)237 uint16_t MtpOperation::GetPayloadDataSub(shared_ptr<MtpOperationContext> &context, shared_ptr<PayloadData> &data,
238     uint16_t containerType, int &errorCode)
239 {
240     responseCode_ = MTP_UNDEFINED_CODE;
241     CHECK_AND_RETURN_RET_LOG(!MtpGlobal::IsBlocked(), responseCode_, "Not support operation in blocked mode");
242     switch (context->operationCode) {
243         case MTP_OPERATION_RESET_DEVICE_CODE:
244         case MTP_OPERATION_CLOSE_SESSION_CODE:
245             responseCode_ = operationUtils_->GetCloseSession(data);
246             break;
247         case MTP_OPERATION_GET_STORAGE_IDS_CODE:
248             responseCode_ = operationUtils_->GetStorageIDs(data, containerType, errorCode);
249             break;
250         case MTP_OPERATION_GET_STORAGE_INFO_CODE:
251             responseCode_ = operationUtils_->GetStorageInfo(data, containerType, errorCode);
252             break;
253         case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED_CODE:
254             responseCode_ = operationUtils_->GetObjectPropsSupported(data);
255             break;
256         case MTP_OPERATION_GET_OBJECT_HANDLES_CODE:
257             responseCode_ = operationUtils_->GetObjectHandles(data, containerType, errorCode);
258             break;
259         case MTP_OPERATION_GET_NUM_OBJECTS_CODE:
260             responseCode_ = operationUtils_->GetNumObjects(data);
261             break;
262         case MTP_OPERATION_GET_OBJECT_INFO_CODE:
263             responseCode_ = operationUtils_->GetObjectInfo(data, containerType, errorCode);
264             break;
265         case MTP_OPERATION_GET_OBJECT_PROP_DESC_CODE:
266             responseCode_ = operationUtils_->GetObjectPropDesc(data, containerType, errorCode);
267             break;
268         case MTP_OPERATION_GET_OBJECT_PROP_VALUE_CODE:
269             responseCode_ = operationUtils_->GetObjectPropValue(data, containerType, errorCode);
270             break;
271         case MTP_OPERATION_SET_OBJECT_PROP_VALUE_CODE:
272             responseCode_ = operationUtils_->GetRespCommonData(data, errorCode);
273             break;
274         case MTP_OPERATION_GET_OBJECT_PROP_LIST_CODE:
275             responseCode_ = operationUtils_->GetObjectPropList(data, containerType, errorCode);
276             break;
277         default:
278             responseCode_ = GetPayloadDataMore(context, data, containerType, errorCode);
279             break;
280     }
281     return responseCode_;
282 }
283 
GetPayloadDataMore(shared_ptr<MtpOperationContext> & context,shared_ptr<PayloadData> & data,uint16_t containerType,int & errorCode)284 uint16_t MtpOperation::GetPayloadDataMore(shared_ptr<MtpOperationContext> &context, shared_ptr<PayloadData> &data,
285     uint16_t containerType, int &errorCode)
286 {
287     responseCode_ = MTP_UNDEFINED_CODE;
288     switch (context->operationCode) {
289         case MTP_OPERATION_GET_OBJECT_REFERENCES_CODE:
290             responseCode_ = operationUtils_->GetObjectReferences(data, containerType, errorCode);
291             break;
292         case MTP_OPERATION_SET_OBJECT_REFERENCES_CODE:
293             responseCode_ = operationUtils_->SetObjectReferences(data);
294             break;
295         case MTP_OPERATION_DELETE_OBJECT_CODE:
296             responseCode_ = operationUtils_->DeleteObject(data, errorCode);
297             break;
298         case MTP_OPERATION_MOVE_OBJECT_CODE:
299             responseCode_ = operationUtils_->MoveObject(data, errorCode);
300             break;
301         case MTP_OPERATION_COPY_OBJECT_CODE:
302             responseCode_ = operationUtils_->CopyObject(data, errorCode);
303             break;
304         case MTP_OPERATION_GET_DEVICE_PROP_DESC_CODE:
305             responseCode_ = operationUtils_->GetPropDesc(data, containerType, errorCode);
306             break;
307         case MTP_OPERATION_GET_DEVICE_PROP_VALUE_CODE:
308             responseCode_ = operationUtils_->GetPropValue(data, containerType, errorCode);
309             break;
310         case MTP_OPERATION_RESET_DEVICE_PROP_VALUE_CODE:
311             responseCode_ = operationUtils_->ResetDevicePropResp(data);
312             break;
313         case MTP_OPERATION_GET_OBJECT_CODE:
314             responseCode_ = operationUtils_->GetObject(data, errorCode);
315             break;
316         case MTP_OPERATION_SEND_OBJECT_CODE:
317             responseCode_ = operationUtils_->GetRespCommonData(data, errorCode);
318             break;
319         case MTP_OPERATION_GET_THUMB_CODE:
320             responseCode_ = operationUtils_->GetThumb(data, containerType, errorCode);
321             break;
322         case MTP_OPERATION_SEND_OBJECT_INFO_CODE:
323             responseCode_ = operationUtils_->SendObjectInfo(data, errorCode);
324             break;
325         case MTP_OPERATION_GET_PARTIAL_OBJECT_CODE:
326             responseCode_ = operationUtils_->GetPartialObject(data);
327             break;
328         default:
329             responseCode_ = operationUtils_->GetRespCommonData(data, errorCode);
330             break;
331     }
332     return responseCode_;
333 }
334 
ResetOperation()335 void MtpOperation::ResetOperation()
336 {
337     if (requestPacketPtr_ != nullptr) {
338         requestPacketPtr_->Reset();
339     }
340     if (dataPacketPtr_ != nullptr) {
341         dataPacketPtr_->Reset();
342     }
343     if (responsePacketPtr_ != nullptr) {
344         responsePacketPtr_->Reset();
345     }
346     if (dataPayloadData_!= nullptr) {
347         dataPayloadData_ = nullptr;
348     }
349     if (mtpContextPtr_ != nullptr) {
350         mtpContextPtr_->operationCode = 0;
351         mtpContextPtr_->transactionID = 0;
352         mtpContextPtr_->indata = false;
353     }
354 
355     responseCode_ = MTP_OK_CODE;
356 }
357 
AddStorage(shared_ptr<Storage> & storage)358 void MtpOperation::AddStorage(shared_ptr<Storage> &storage)
359 {
360     auto mtpStorageManager = MtpStorageManager::GetInstance();
361     if (mtpStorageManager != nullptr) {
362         mtpStorageManager->AddStorage(storage);
363     }
364 }
365 
RemoveStorage(std::shared_ptr<Storage> & storage)366 void MtpOperation::RemoveStorage(std::shared_ptr<Storage> &storage)
367 {
368     auto mtpStorageManager = MtpStorageManager::GetInstance();
369     if (mtpStorageManager != nullptr) {
370         mtpStorageManager->RemoveStorage(storage);
371     }
372 }
373 } // namespace Media
374 } // namespace OHOS