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