• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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