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 #include "mtp_packet.h"
16 #include "media_log.h"
17 #include "media_mtp_utils.h"
18 #include "mtp_constants.h"
19 #include "packet_payload_factory.h"
20 using namespace std;
21 namespace OHOS {
22 namespace Media {
23 const int EVENT_LENGTH = 16;
24 const uint32_t BATCH_SIZE = 200000;
25
MtpPacket(std::shared_ptr<MtpOperationContext> & context)26 MtpPacket::MtpPacket(std::shared_ptr<MtpOperationContext> &context)
27 : context_(context), readSize_(0), headerData_(nullptr), payloadData_(nullptr)
28 {
29 }
30
MtpPacket(std::shared_ptr<MtpOperationContext> & context,const shared_ptr<MtpDriver> & mtpDriver)31 MtpPacket::MtpPacket(std::shared_ptr<MtpOperationContext> &context, const shared_ptr<MtpDriver> &mtpDriver)
32 : context_(context), readSize_(0), headerData_(nullptr), payloadData_(nullptr), mtpDriver_(mtpDriver)
33 {
34 }
35
~MtpPacket()36 MtpPacket::~MtpPacket()
37 {
38 }
39
Init(std::shared_ptr<HeaderData> & headerData)40 void MtpPacket::Init(std::shared_ptr<HeaderData> &headerData)
41 {
42 CHECK_AND_RETURN_LOG(headerData != nullptr, "Init failed, headerData is nullptr");
43
44 readSize_ = 0;
45 headerData_ = headerData;
46
47 if (headerData->GetContainerType() == DATA_CONTAINER_TYPE) {
48 readBufSize_ = READ_DATA_BUFFER_MAX_SIZE;
49 } else {
50 readBufSize_ = READ_BUFFER_MAX_SIZE;
51 }
52 }
53
Init(std::shared_ptr<HeaderData> & headerData,std::shared_ptr<PayloadData> & payloadData)54 void MtpPacket::Init(std::shared_ptr<HeaderData> &headerData, std::shared_ptr<PayloadData> &payloadData)
55 {
56 CHECK_AND_RETURN_LOG(headerData != nullptr, "Init failed, headerData is nullptr");
57 CHECK_AND_RETURN_LOG(payloadData != nullptr, "Init failed, payloadData is nullptr");
58
59 readSize_ = 0;
60 headerData_ = headerData;
61 payloadData_ = payloadData;
62
63 if (headerData->GetContainerType() == DATA_CONTAINER_TYPE) {
64 readBufSize_ = READ_DATA_BUFFER_MAX_SIZE;
65 } else {
66 readBufSize_ = READ_BUFFER_MAX_SIZE;
67 }
68 }
69
Reset()70 void MtpPacket::Reset()
71 {
72 readSize_ = 0;
73 headerData_ = nullptr;
74 payloadData_ = nullptr;
75 std::vector<uint8_t>().swap(writeBuffer_);
76 }
77
Stop()78 void MtpPacket::Stop()
79 {
80 CHECK_AND_RETURN_LOG(mtpDriver_ != nullptr, "mtpDriver_ is null");
81 (void)mtpDriver_->CloseDriver();
82 }
83
IsNeedDataPhase(uint16_t operationCode)84 bool MtpPacket::IsNeedDataPhase(uint16_t operationCode)
85 {
86 switch (operationCode) {
87 case MTP_OPERATION_GET_DEVICE_INFO_CODE:
88 case MTP_OPERATION_GET_STORAGE_IDS_CODE:
89 case MTP_OPERATION_GET_STORAGE_INFO_CODE:
90 case MTP_OPERATION_GET_OBJECT_HANDLES_CODE:
91 case MTP_OPERATION_GET_OBJECT_CODE:
92 case MTP_OPERATION_GET_OBJECT_INFO_CODE:
93 case MTP_OPERATION_GET_THUMB_CODE:
94 case MTP_OPERATION_SEND_OBJECT_INFO_CODE:
95 case MTP_OPERATION_SEND_OBJECT_CODE:
96 case MTP_OPERATION_GET_DEVICE_PROP_DESC_CODE:
97 case MTP_OPERATION_GET_DEVICE_PROP_VALUE_CODE:
98 case MTP_OPERATION_SET_DEVICE_PROP_VALUE_CODE:
99 case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED_CODE:
100 case MTP_OPERATION_GET_OBJECT_PROP_DESC_CODE:
101 case MTP_OPERATION_GET_OBJECT_PROP_VALUE_CODE:
102 case MTP_OPERATION_SET_OBJECT_PROP_VALUE_CODE:
103 case MTP_OPERATION_GET_OBJECT_PROP_LIST_CODE:
104 case MTP_OPERATION_GET_OBJECT_REFERENCES_CODE:
105 case MTP_OPERATION_GET_PARTIAL_OBJECT_CODE:
106 return true;
107 default:
108 break;
109 }
110 return false;
111 }
112
IsI2R(uint16_t operationCode)113 bool MtpPacket::IsI2R(uint16_t operationCode)
114 {
115 switch (operationCode) {
116 case MTP_OPERATION_SEND_OBJECT_INFO_CODE:
117 case MTP_OPERATION_SEND_OBJECT_CODE:
118 case MTP_OPERATION_SET_DEVICE_PROP_VALUE_CODE:
119 case MTP_OPERATION_SET_OBJECT_PROP_VALUE_CODE:
120 return true;
121 default:
122 break;
123 }
124 return false;
125 }
126
Read()127 int MtpPacket::Read()
128 {
129 CHECK_AND_RETURN_RET_LOG(mtpDriver_ != nullptr,
130 MTP_ERROR_DRIVER_OPEN_FAILED, "Read failed, mtpDriver_ is nullptr");
131
132 std::vector<uint8_t>().swap(readBuffer_);
133 int errorCode = mtpDriver_->Read(readBuffer_, readSize_);
134 return errorCode;
135 }
136
Write(int32_t & result)137 int MtpPacket::Write(int32_t &result)
138 {
139 CHECK_AND_RETURN_RET_LOG(mtpDriver_ != nullptr,
140 MTP_ERROR_DRIVER_OPEN_FAILED, "Write failed, mtpDriver_ is nullptr");
141 CHECK_AND_RETURN_RET_LOG(headerData_ != nullptr, MTP_FAIL, "Write failed, headerData_ is nullptr");
142
143 if (headerData_->GetContainerType() == EVENT_CONTAINER_TYPE) {
144 EventMtp event;
145 event.length = EVENT_LENGTH;
146 event.data = writeBuffer_;
147 result = mtpDriver_->WriteEvent(event);
148 return MTP_SUCCESS;
149 }
150 // Due to the USB module using IPC for communication, and the maximum length supported by IPC is 248000,
151 // when the write buffer is too large, it needs to be split into multiple calls.
152 if (writeBuffer_.size() > BATCH_SIZE) {
153 uint32_t total = writeBuffer_.size();
154 for (uint32_t i = 0; i < writeBuffer_.size(); i += BATCH_SIZE) {
155 uint32_t end = std::min(i + BATCH_SIZE, total);
156 std::vector<uint8_t> batch(writeBuffer_.begin() + i, writeBuffer_.begin() + end);
157 mtpDriver_->Write(batch, end, result);
158 std::vector<uint8_t>().swap(batch);
159 }
160 } else {
161 mtpDriver_->Write(writeBuffer_, writeSize_, result);
162 }
163 return MTP_SUCCESS;
164 }
165
Parser()166 int MtpPacket::Parser()
167 {
168 int errorCode = ParserHead();
169 CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, errorCode, "ParserHead fail err: %{public}d", errorCode);
170
171 errorCode = ParserPayload();
172 CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, errorCode, "ParserPayload fail err: %{public}d", errorCode);
173 return MTP_SUCCESS;
174 }
175
Maker(bool isPayload)176 int MtpPacket::Maker(bool isPayload)
177 {
178 CHECK_AND_RETURN_RET_LOG(payloadData_ != nullptr, MTP_FAIL, "Maker failed, payloadData_ is nullptr");
179 CHECK_AND_RETURN_RET_LOG(headerData_ != nullptr, MTP_FAIL, "Maker failed, headerData_ is nullptr");
180
181 writeSize_ = payloadData_->CalculateSize() + PACKET_HEADER_LENGETH;
182 headerData_->SetContainerLength(writeSize_);
183
184 int errorCode = MakeHead();
185 CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, errorCode, "MakeHead fail err: %{public}d", errorCode);
186
187 errorCode = MakerPayload();
188 CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, errorCode, "MakeHead fail err: %{public}d", errorCode);
189 return MTP_SUCCESS;
190 }
191
ParserHead()192 int MtpPacket::ParserHead()
193 {
194 CHECK_AND_RETURN_RET_LOG(readSize_ > 0, MTP_ERROR_PACKET_INCORRECT, "ParserHead fail readSize_ <= 0");
195 if (headerData_ == nullptr) {
196 headerData_ = make_shared<HeaderData>(context_);
197 }
198 int errorCode = headerData_->Parser(readBuffer_, readSize_);
199 CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, errorCode, "PacketHeader Parser fail err: %{public}d",
200 errorCode);
201 return MTP_SUCCESS;
202 }
203
ParserPayload()204 int MtpPacket::ParserPayload()
205 {
206 CHECK_AND_RETURN_RET_LOG(headerData_ != nullptr, MTP_ERROR_PACKET_INCORRECT,
207 "ParserPayload failed, headerData_ is nullptr");
208
209 CHECK_AND_RETURN_RET_LOG(readSize_ > 0, MTP_ERROR_PACKET_INCORRECT, "ParserPayload fail readSize_ <= 0");
210 CHECK_AND_RETURN_RET_LOG(headerData_->GetCode() != 0, MTP_ERROR_PACKET_INCORRECT, "GetOperationCode fail");
211 CHECK_AND_RETURN_RET_LOG(headerData_->GetContainerType() != 0, MTP_ERROR_PACKET_INCORRECT, "GetOperationCode fail");
212
213 payloadData_ = PacketPayloadFactory::CreatePayload(context_,
214 headerData_->GetCode(), headerData_->GetContainerType());
215 CHECK_AND_RETURN_RET_LOG(payloadData_ != nullptr, MTP_FAIL, "payloadData_ is nullptr");
216
217 int errorCode = payloadData_->Parser(readBuffer_, readSize_);
218 CHECK_AND_PRINT_LOG(errorCode == MTP_SUCCESS, "PacketHeader Parser fail err: %{public}d", errorCode);
219 return errorCode;
220 }
221
MakeHead()222 int MtpPacket::MakeHead()
223 {
224 CHECK_AND_RETURN_RET_LOG(headerData_ != nullptr, MTP_SUCCESS, "headerData_ is null!");
225
226 int errorCode = headerData_->Maker(writeBuffer_);
227 CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, errorCode, "HeaderData Make fail err: %{public}d", errorCode);
228 return MTP_SUCCESS;
229 }
230
MakerPayload()231 int MtpPacket::MakerPayload()
232 {
233 CHECK_AND_RETURN_RET_LOG(payloadData_ != nullptr, MTP_SUCCESS, "payloadData_ is null!");
234
235 int errorCode = payloadData_->Maker(writeBuffer_);
236 CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, errorCode, "PayloadData Make fail err: %{public}d", errorCode);
237 return MTP_SUCCESS;
238 }
239
GetOperationCode()240 uint16_t MtpPacket::GetOperationCode()
241 {
242 CHECK_AND_RETURN_RET_LOG(headerData_ != nullptr, MTP_FAIL, "GetOperationCode failed, headerData_ is nullptr");
243 return headerData_->GetCode();
244 }
245
GetTransactionId()246 uint32_t MtpPacket::GetTransactionId()
247 {
248 CHECK_AND_RETURN_RET_LOG(headerData_ != nullptr, MTP_FAIL, "GetTransactionId failed, headerData_ is nullptr");
249 return headerData_->GetTransactionId();
250 }
251
GetSessionID()252 uint32_t MtpPacket::GetSessionID()
253 {
254 return 0;
255 }
256 } // namespace Media
257 } // namespace OHOS
258