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
IsNeedDataPhase(uint16_t operationCode)78 bool MtpPacket::IsNeedDataPhase(uint16_t operationCode)
79 {
80 switch (operationCode) {
81 case MTP_OPERATION_GET_DEVICE_INFO_CODE:
82 case MTP_OPERATION_GET_STORAGE_IDS_CODE:
83 case MTP_OPERATION_GET_STORAGE_INFO_CODE:
84 case MTP_OPERATION_GET_OBJECT_HANDLES_CODE:
85 case MTP_OPERATION_GET_OBJECT_CODE:
86 case MTP_OPERATION_GET_OBJECT_INFO_CODE:
87 case MTP_OPERATION_GET_THUMB_CODE:
88 case MTP_OPERATION_SEND_OBJECT_INFO_CODE:
89 case MTP_OPERATION_SEND_OBJECT_CODE:
90 case MTP_OPERATION_GET_DEVICE_PROP_DESC_CODE:
91 case MTP_OPERATION_SET_DEVICE_PROP_VALUE_CODE:
92 case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED_CODE:
93 case MTP_OPERATION_GET_OBJECT_PROP_DESC_CODE:
94 case MTP_OPERATION_GET_OBJECT_PROP_VALUE_CODE:
95 case MTP_OPERATION_SET_OBJECT_PROP_VALUE_CODE:
96 case MTP_OPERATION_GET_OBJECT_PROP_LIST_CODE:
97 case MTP_OPERATION_GET_OBJECT_REFERENCES_CODE:
98 return true;
99 default:
100 break;
101 }
102 return false;
103 }
104
IsI2R(uint16_t operationCode)105 bool MtpPacket::IsI2R(uint16_t operationCode)
106 {
107 switch (operationCode) {
108 case MTP_OPERATION_SEND_OBJECT_INFO_CODE:
109 case MTP_OPERATION_SEND_OBJECT_CODE:
110 case MTP_OPERATION_SET_DEVICE_PROP_VALUE_CODE:
111 case MTP_OPERATION_SET_OBJECT_PROP_VALUE_CODE:
112 return true;
113 default:
114 break;
115 }
116 return false;
117 }
118
Read()119 int MtpPacket::Read()
120 {
121 CHECK_AND_RETURN_RET_LOG(mtpDriver_ != nullptr,
122 MTP_ERROR_DRIVER_OPEN_FAILED, "Read failed, mtpDriver_ is nullptr");
123
124 std::vector<uint8_t>().swap(readBuffer_);
125 int errorCode = mtpDriver_->Read(readBuffer_, readSize_);
126 return errorCode;
127 }
128
Write()129 int MtpPacket::Write()
130 {
131 CHECK_AND_RETURN_RET_LOG(mtpDriver_ != nullptr,
132 MTP_ERROR_DRIVER_OPEN_FAILED, "Write failed, mtpDriver_ is nullptr");
133 CHECK_AND_RETURN_RET_LOG(headerData_ != nullptr, MTP_FAIL, "Write failed, headerData_ is nullptr");
134
135 if (headerData_->GetContainerType() == EVENT_CONTAINER_TYPE) {
136 EventMtp event;
137 event.length = EVENT_LENGTH;
138 event.data = writeBuffer_;
139 mtpDriver_->WriteEvent(event);
140 return MTP_SUCCESS;
141 }
142 // Due to the USB module using IPC for communication, and the maximum length supported by IPC is 248000,
143 // when the write buffer is too large, it needs to be split into multiple calls.
144 if (writeBuffer_.size() > BATCH_SIZE) {
145 uint32_t total = writeBuffer_.size();
146 for (uint32_t i = 0; i < writeBuffer_.size(); i += BATCH_SIZE) {
147 uint32_t end = std::min(i + BATCH_SIZE, total);
148 std::vector<uint8_t> batch(writeBuffer_.begin() + i, writeBuffer_.begin() + end);
149 mtpDriver_->Write(batch, end);
150 std::vector<uint8_t>().swap(batch);
151 }
152 } else {
153 mtpDriver_->Write(writeBuffer_, writeSize_);
154 }
155 return MTP_SUCCESS;
156 }
157
Parser()158 int MtpPacket::Parser()
159 {
160 int errorCode = ParserHead();
161 if (errorCode != MTP_SUCCESS) {
162 MEDIA_ERR_LOG("ParserHead fail err: %{public}d", errorCode);
163 return errorCode;
164 }
165
166 errorCode = ParserPayload();
167 if (errorCode != MTP_SUCCESS) {
168 MEDIA_ERR_LOG("ParserPayload fail err: %{public}d", errorCode);
169 return errorCode;
170 }
171 return MTP_SUCCESS;
172 }
173
Maker(bool isPayload)174 int MtpPacket::Maker(bool isPayload)
175 {
176 CHECK_AND_RETURN_RET_LOG(payloadData_ != nullptr, MTP_FAIL, "Maker failed, payloadData_ is nullptr");
177 CHECK_AND_RETURN_RET_LOG(headerData_ != nullptr, MTP_FAIL, "Maker failed, headerData_ is nullptr");
178
179 writeSize_ = payloadData_->CalculateSize() + PACKET_HEADER_LENGETH;
180 headerData_->SetContainerLength(writeSize_);
181
182 int errorCode = MakeHead();
183 if (errorCode != MTP_SUCCESS) {
184 MEDIA_ERR_LOG("MakeHead fail err: %{public}d", errorCode);
185 return errorCode;
186 }
187
188 errorCode = MakerPayload();
189 if (errorCode != MTP_SUCCESS) {
190 MEDIA_ERR_LOG("MakeHead fail err: %{public}d", errorCode);
191 return errorCode;
192 }
193 return MTP_SUCCESS;
194 }
195
ParserHead()196 int MtpPacket::ParserHead()
197 {
198 if (readSize_ <= 0) {
199 MEDIA_ERR_LOG("ParserHead fail readSize_ <= 0");
200 return MTP_ERROR_PACKET_INCORRECT;
201 }
202 if (headerData_ == nullptr) {
203 headerData_ = make_shared<HeaderData>(context_);
204 }
205 int errorCode = headerData_->Parser(readBuffer_, readSize_);
206 if (errorCode != MTP_SUCCESS) {
207 MEDIA_ERR_LOG("PacketHeader Parser fail err: %{public}d", errorCode);
208 return errorCode;
209 }
210 return MTP_SUCCESS;
211 }
212
ParserPayload()213 int MtpPacket::ParserPayload()
214 {
215 CHECK_AND_RETURN_RET_LOG(headerData_ != nullptr, MTP_ERROR_PACKET_INCORRECT,
216 "ParserPayload failed, headerData_ is nullptr");
217
218 if (readSize_ <= 0) {
219 MEDIA_ERR_LOG("ParserPayload fail readSize_ <= 0");
220 return MTP_ERROR_PACKET_INCORRECT;
221 }
222 if (headerData_->GetCode() == 0) {
223 MEDIA_ERR_LOG("GetOperationCode fail");
224 return MTP_ERROR_PACKET_INCORRECT;
225 }
226
227 if (headerData_->GetContainerType() == 0) {
228 MEDIA_ERR_LOG("GetOperationCode fail");
229 return MTP_ERROR_PACKET_INCORRECT;
230 }
231
232 payloadData_ = PacketPayloadFactory::CreatePayload(context_,
233 headerData_->GetCode(), headerData_->GetContainerType());
234 if (payloadData_ == nullptr) {
235 MEDIA_ERR_LOG("payloadData_ is nullptr");
236 return MTP_FAIL;
237 }
238
239 int errorCode = payloadData_->Parser(readBuffer_, readSize_);
240 if (errorCode != MTP_SUCCESS) {
241 MEDIA_ERR_LOG("PacketHeader Parser fail err: %{public}d", errorCode);
242 }
243 return errorCode;
244 }
245
MakeHead()246 int MtpPacket::MakeHead()
247 {
248 if (headerData_ == nullptr) {
249 MEDIA_ERR_LOG("headerData_ is null!");
250 return MTP_SUCCESS;
251 }
252
253 int errorCode = headerData_->Maker(writeBuffer_);
254 if (errorCode != MTP_SUCCESS) {
255 MEDIA_ERR_LOG("HeaderData Make fail err: %{public}d", errorCode);
256 return errorCode;
257 }
258 return MTP_SUCCESS;
259 }
260
MakerPayload()261 int MtpPacket::MakerPayload()
262 {
263 if (payloadData_ == nullptr) {
264 MEDIA_ERR_LOG("payloadData_ is null!");
265 return MTP_SUCCESS;
266 }
267
268 int errorCode = payloadData_->Maker(writeBuffer_);
269 if (errorCode != MTP_SUCCESS) {
270 MEDIA_ERR_LOG("PayloadData Make fail err: %{public}d", errorCode);
271 return errorCode;
272 }
273 return MTP_SUCCESS;
274 }
275
GetOperationCode()276 uint16_t MtpPacket::GetOperationCode()
277 {
278 CHECK_AND_RETURN_RET_LOG(headerData_ != nullptr, MTP_FAIL, "GetOperationCode failed, headerData_ is nullptr");
279 return headerData_->GetCode();
280 }
281
GetTransactionId()282 uint32_t MtpPacket::GetTransactionId()
283 {
284 CHECK_AND_RETURN_RET_LOG(headerData_ != nullptr, MTP_FAIL, "GetTransactionId failed, headerData_ is nullptr");
285 return headerData_->GetTransactionId();
286 }
287
GetSessionID()288 uint32_t MtpPacket::GetSessionID()
289 {
290 return 0;
291 }
292 } // namespace Media
293 } // namespace OHOS
294