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