xref: /aosp_15_r20/frameworks/av/media/mtp/MtpDataPacket.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2010 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "MtpDataPacket"
18*ec779b8eSAndroid Build Coastguard Worker 
19*ec779b8eSAndroid Build Coastguard Worker #include "MtpDataPacket.h"
20*ec779b8eSAndroid Build Coastguard Worker 
21*ec779b8eSAndroid Build Coastguard Worker #include <algorithm>
22*ec779b8eSAndroid Build Coastguard Worker #include <errno.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <fcntl.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <stdio.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <sys/types.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <usbhost/usbhost.h>
27*ec779b8eSAndroid Build Coastguard Worker #include "MtpStringBuffer.h"
28*ec779b8eSAndroid Build Coastguard Worker #include "IMtpHandle.h"
29*ec779b8eSAndroid Build Coastguard Worker 
30*ec779b8eSAndroid Build Coastguard Worker namespace android {
31*ec779b8eSAndroid Build Coastguard Worker 
32*ec779b8eSAndroid Build Coastguard Worker namespace {
33*ec779b8eSAndroid Build Coastguard Worker // Reads the exact |count| bytes from |fd| to |buf|.
34*ec779b8eSAndroid Build Coastguard Worker // Returns |count| if it succeed to read the bytes. Otherwise returns -1. If it reaches EOF, the
35*ec779b8eSAndroid Build Coastguard Worker // function regards it as an error.
readExactBytes(int fd,void * buf,size_t count)36*ec779b8eSAndroid Build Coastguard Worker ssize_t readExactBytes(int fd, void* buf, size_t count) {
37*ec779b8eSAndroid Build Coastguard Worker     if (count > SSIZE_MAX) {
38*ec779b8eSAndroid Build Coastguard Worker         return -1;
39*ec779b8eSAndroid Build Coastguard Worker     }
40*ec779b8eSAndroid Build Coastguard Worker     size_t read_count = 0;
41*ec779b8eSAndroid Build Coastguard Worker     while (read_count < count) {
42*ec779b8eSAndroid Build Coastguard Worker         int result = read(fd, static_cast<int8_t*>(buf) + read_count, count - read_count);
43*ec779b8eSAndroid Build Coastguard Worker         // Assume that EOF is error.
44*ec779b8eSAndroid Build Coastguard Worker         if (result <= 0) {
45*ec779b8eSAndroid Build Coastguard Worker             return -1;
46*ec779b8eSAndroid Build Coastguard Worker         }
47*ec779b8eSAndroid Build Coastguard Worker         read_count += result;
48*ec779b8eSAndroid Build Coastguard Worker     }
49*ec779b8eSAndroid Build Coastguard Worker     return read_count == count ? count : -1;
50*ec779b8eSAndroid Build Coastguard Worker }
51*ec779b8eSAndroid Build Coastguard Worker }  // namespace
52*ec779b8eSAndroid Build Coastguard Worker 
MtpDataPacket()53*ec779b8eSAndroid Build Coastguard Worker MtpDataPacket::MtpDataPacket()
54*ec779b8eSAndroid Build Coastguard Worker     :   MtpPacket(MTP_BUFFER_SIZE),   // MAX_USBFS_BUFFER_SIZE
55*ec779b8eSAndroid Build Coastguard Worker         mOffset(MTP_CONTAINER_HEADER_SIZE)
56*ec779b8eSAndroid Build Coastguard Worker {
57*ec779b8eSAndroid Build Coastguard Worker }
58*ec779b8eSAndroid Build Coastguard Worker 
~MtpDataPacket()59*ec779b8eSAndroid Build Coastguard Worker MtpDataPacket::~MtpDataPacket() {
60*ec779b8eSAndroid Build Coastguard Worker }
61*ec779b8eSAndroid Build Coastguard Worker 
reset()62*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::reset() {
63*ec779b8eSAndroid Build Coastguard Worker     MtpPacket::reset();
64*ec779b8eSAndroid Build Coastguard Worker     mOffset = MTP_CONTAINER_HEADER_SIZE;
65*ec779b8eSAndroid Build Coastguard Worker }
66*ec779b8eSAndroid Build Coastguard Worker 
setOperationCode(MtpOperationCode code)67*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::setOperationCode(MtpOperationCode code) {
68*ec779b8eSAndroid Build Coastguard Worker     MtpPacket::putUInt16(MTP_CONTAINER_CODE_OFFSET, code);
69*ec779b8eSAndroid Build Coastguard Worker }
70*ec779b8eSAndroid Build Coastguard Worker 
setTransactionID(MtpTransactionID id)71*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::setTransactionID(MtpTransactionID id) {
72*ec779b8eSAndroid Build Coastguard Worker     MtpPacket::putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);
73*ec779b8eSAndroid Build Coastguard Worker }
74*ec779b8eSAndroid Build Coastguard Worker 
getUInt8(uint8_t & value)75*ec779b8eSAndroid Build Coastguard Worker bool MtpDataPacket::getUInt8(uint8_t& value) {
76*ec779b8eSAndroid Build Coastguard Worker     if ((mPacketSize - mOffset < sizeof(value)) || (mOffset >= mBufferSize))
77*ec779b8eSAndroid Build Coastguard Worker         return false;
78*ec779b8eSAndroid Build Coastguard Worker     value = mBuffer[mOffset++];
79*ec779b8eSAndroid Build Coastguard Worker     return true;
80*ec779b8eSAndroid Build Coastguard Worker }
81*ec779b8eSAndroid Build Coastguard Worker 
getUInt16(uint16_t & value)82*ec779b8eSAndroid Build Coastguard Worker bool MtpDataPacket::getUInt16(uint16_t& value) {
83*ec779b8eSAndroid Build Coastguard Worker     if ((mPacketSize - mOffset < sizeof(value)) || ((mOffset+1) >= mBufferSize))
84*ec779b8eSAndroid Build Coastguard Worker         return false;
85*ec779b8eSAndroid Build Coastguard Worker     int offset = mOffset;
86*ec779b8eSAndroid Build Coastguard Worker     value = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8);
87*ec779b8eSAndroid Build Coastguard Worker     mOffset += sizeof(value);
88*ec779b8eSAndroid Build Coastguard Worker     return true;
89*ec779b8eSAndroid Build Coastguard Worker }
90*ec779b8eSAndroid Build Coastguard Worker 
getUInt32(uint32_t & value)91*ec779b8eSAndroid Build Coastguard Worker bool MtpDataPacket::getUInt32(uint32_t& value) {
92*ec779b8eSAndroid Build Coastguard Worker     if ((mPacketSize - mOffset < sizeof(value)) || ((mOffset+3) >= mBufferSize))
93*ec779b8eSAndroid Build Coastguard Worker         return false;
94*ec779b8eSAndroid Build Coastguard Worker     int offset = mOffset;
95*ec779b8eSAndroid Build Coastguard Worker     value = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) |
96*ec779b8eSAndroid Build Coastguard Worker            ((uint32_t)mBuffer[offset + 2] << 16)  | ((uint32_t)mBuffer[offset + 3] << 24);
97*ec779b8eSAndroid Build Coastguard Worker     mOffset += sizeof(value);
98*ec779b8eSAndroid Build Coastguard Worker     return true;
99*ec779b8eSAndroid Build Coastguard Worker }
100*ec779b8eSAndroid Build Coastguard Worker 
getUInt64(uint64_t & value)101*ec779b8eSAndroid Build Coastguard Worker bool MtpDataPacket::getUInt64(uint64_t& value) {
102*ec779b8eSAndroid Build Coastguard Worker     if ((mPacketSize - mOffset < sizeof(value)) || ((mOffset+7) >= mBufferSize))
103*ec779b8eSAndroid Build Coastguard Worker         return false;
104*ec779b8eSAndroid Build Coastguard Worker     int offset = mOffset;
105*ec779b8eSAndroid Build Coastguard Worker     value = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) |
106*ec779b8eSAndroid Build Coastguard Worker            ((uint64_t)mBuffer[offset + 2] << 16) | ((uint64_t)mBuffer[offset + 3] << 24) |
107*ec779b8eSAndroid Build Coastguard Worker            ((uint64_t)mBuffer[offset + 4] << 32) | ((uint64_t)mBuffer[offset + 5] << 40) |
108*ec779b8eSAndroid Build Coastguard Worker            ((uint64_t)mBuffer[offset + 6] << 48)  | ((uint64_t)mBuffer[offset + 7] << 56);
109*ec779b8eSAndroid Build Coastguard Worker     mOffset += sizeof(value);
110*ec779b8eSAndroid Build Coastguard Worker     return true;
111*ec779b8eSAndroid Build Coastguard Worker }
112*ec779b8eSAndroid Build Coastguard Worker 
getUInt128(uint128_t & value)113*ec779b8eSAndroid Build Coastguard Worker bool MtpDataPacket::getUInt128(uint128_t& value) {
114*ec779b8eSAndroid Build Coastguard Worker     return getUInt32(value[0]) && getUInt32(value[1]) && getUInt32(value[2]) && getUInt32(value[3]);
115*ec779b8eSAndroid Build Coastguard Worker }
116*ec779b8eSAndroid Build Coastguard Worker 
getString(MtpStringBuffer & string)117*ec779b8eSAndroid Build Coastguard Worker bool MtpDataPacket::getString(MtpStringBuffer& string)
118*ec779b8eSAndroid Build Coastguard Worker {
119*ec779b8eSAndroid Build Coastguard Worker     return string.readFromPacket(this);
120*ec779b8eSAndroid Build Coastguard Worker }
121*ec779b8eSAndroid Build Coastguard Worker 
getAInt8()122*ec779b8eSAndroid Build Coastguard Worker Int8List* MtpDataPacket::getAInt8() {
123*ec779b8eSAndroid Build Coastguard Worker     uint32_t count;
124*ec779b8eSAndroid Build Coastguard Worker     if (!getUInt32(count))
125*ec779b8eSAndroid Build Coastguard Worker         return NULL;
126*ec779b8eSAndroid Build Coastguard Worker     Int8List* result = new Int8List;
127*ec779b8eSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < count; i++) {
128*ec779b8eSAndroid Build Coastguard Worker         int8_t value;
129*ec779b8eSAndroid Build Coastguard Worker         if (!getInt8(value)) {
130*ec779b8eSAndroid Build Coastguard Worker             delete result;
131*ec779b8eSAndroid Build Coastguard Worker             return NULL;
132*ec779b8eSAndroid Build Coastguard Worker         }
133*ec779b8eSAndroid Build Coastguard Worker         result->push_back(value);
134*ec779b8eSAndroid Build Coastguard Worker     }
135*ec779b8eSAndroid Build Coastguard Worker     return result;
136*ec779b8eSAndroid Build Coastguard Worker }
137*ec779b8eSAndroid Build Coastguard Worker 
getAUInt8()138*ec779b8eSAndroid Build Coastguard Worker UInt8List* MtpDataPacket::getAUInt8() {
139*ec779b8eSAndroid Build Coastguard Worker     uint32_t count;
140*ec779b8eSAndroid Build Coastguard Worker     if (!getUInt32(count))
141*ec779b8eSAndroid Build Coastguard Worker         return NULL;
142*ec779b8eSAndroid Build Coastguard Worker     UInt8List* result = new UInt8List;
143*ec779b8eSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < count; i++) {
144*ec779b8eSAndroid Build Coastguard Worker         uint8_t value;
145*ec779b8eSAndroid Build Coastguard Worker         if (!getUInt8(value)) {
146*ec779b8eSAndroid Build Coastguard Worker             delete result;
147*ec779b8eSAndroid Build Coastguard Worker             return NULL;
148*ec779b8eSAndroid Build Coastguard Worker         }
149*ec779b8eSAndroid Build Coastguard Worker         result->push_back(value);
150*ec779b8eSAndroid Build Coastguard Worker     }
151*ec779b8eSAndroid Build Coastguard Worker     return result;
152*ec779b8eSAndroid Build Coastguard Worker }
153*ec779b8eSAndroid Build Coastguard Worker 
getAInt16()154*ec779b8eSAndroid Build Coastguard Worker Int16List* MtpDataPacket::getAInt16() {
155*ec779b8eSAndroid Build Coastguard Worker     uint32_t count;
156*ec779b8eSAndroid Build Coastguard Worker     if (!getUInt32(count))
157*ec779b8eSAndroid Build Coastguard Worker         return NULL;
158*ec779b8eSAndroid Build Coastguard Worker     Int16List* result = new Int16List;
159*ec779b8eSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < count; i++) {
160*ec779b8eSAndroid Build Coastguard Worker         int16_t value;
161*ec779b8eSAndroid Build Coastguard Worker         if (!getInt16(value)) {
162*ec779b8eSAndroid Build Coastguard Worker             delete result;
163*ec779b8eSAndroid Build Coastguard Worker             return NULL;
164*ec779b8eSAndroid Build Coastguard Worker         }
165*ec779b8eSAndroid Build Coastguard Worker         result->push_back(value);
166*ec779b8eSAndroid Build Coastguard Worker     }
167*ec779b8eSAndroid Build Coastguard Worker     return result;
168*ec779b8eSAndroid Build Coastguard Worker }
169*ec779b8eSAndroid Build Coastguard Worker 
getAUInt16()170*ec779b8eSAndroid Build Coastguard Worker UInt16List* MtpDataPacket::getAUInt16() {
171*ec779b8eSAndroid Build Coastguard Worker     uint32_t count;
172*ec779b8eSAndroid Build Coastguard Worker     if (!getUInt32(count))
173*ec779b8eSAndroid Build Coastguard Worker         return NULL;
174*ec779b8eSAndroid Build Coastguard Worker     UInt16List* result = new UInt16List;
175*ec779b8eSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < count; i++) {
176*ec779b8eSAndroid Build Coastguard Worker         uint16_t value;
177*ec779b8eSAndroid Build Coastguard Worker         if (!getUInt16(value)) {
178*ec779b8eSAndroid Build Coastguard Worker             delete result;
179*ec779b8eSAndroid Build Coastguard Worker             return NULL;
180*ec779b8eSAndroid Build Coastguard Worker         }
181*ec779b8eSAndroid Build Coastguard Worker         result->push_back(value);
182*ec779b8eSAndroid Build Coastguard Worker     }
183*ec779b8eSAndroid Build Coastguard Worker     return result;
184*ec779b8eSAndroid Build Coastguard Worker }
185*ec779b8eSAndroid Build Coastguard Worker 
getAInt32()186*ec779b8eSAndroid Build Coastguard Worker Int32List* MtpDataPacket::getAInt32() {
187*ec779b8eSAndroid Build Coastguard Worker     uint32_t count;
188*ec779b8eSAndroid Build Coastguard Worker     if (!getUInt32(count))
189*ec779b8eSAndroid Build Coastguard Worker         return NULL;
190*ec779b8eSAndroid Build Coastguard Worker     Int32List* result = new Int32List;
191*ec779b8eSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < count; i++) {
192*ec779b8eSAndroid Build Coastguard Worker         int32_t value;
193*ec779b8eSAndroid Build Coastguard Worker         if (!getInt32(value)) {
194*ec779b8eSAndroid Build Coastguard Worker             delete result;
195*ec779b8eSAndroid Build Coastguard Worker             return NULL;
196*ec779b8eSAndroid Build Coastguard Worker         }
197*ec779b8eSAndroid Build Coastguard Worker         result->push_back(value);
198*ec779b8eSAndroid Build Coastguard Worker     }
199*ec779b8eSAndroid Build Coastguard Worker     return result;
200*ec779b8eSAndroid Build Coastguard Worker }
201*ec779b8eSAndroid Build Coastguard Worker 
getAUInt32()202*ec779b8eSAndroid Build Coastguard Worker UInt32List* MtpDataPacket::getAUInt32() {
203*ec779b8eSAndroid Build Coastguard Worker     uint32_t count;
204*ec779b8eSAndroid Build Coastguard Worker     if (!getUInt32(count))
205*ec779b8eSAndroid Build Coastguard Worker         return NULL;
206*ec779b8eSAndroid Build Coastguard Worker     UInt32List* result = new UInt32List;
207*ec779b8eSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < count; i++) {
208*ec779b8eSAndroid Build Coastguard Worker         uint32_t value;
209*ec779b8eSAndroid Build Coastguard Worker         if (!getUInt32(value)) {
210*ec779b8eSAndroid Build Coastguard Worker             delete result;
211*ec779b8eSAndroid Build Coastguard Worker             return NULL;
212*ec779b8eSAndroid Build Coastguard Worker         }
213*ec779b8eSAndroid Build Coastguard Worker         result->push_back(value);
214*ec779b8eSAndroid Build Coastguard Worker     }
215*ec779b8eSAndroid Build Coastguard Worker     return result;
216*ec779b8eSAndroid Build Coastguard Worker }
217*ec779b8eSAndroid Build Coastguard Worker 
getAInt64()218*ec779b8eSAndroid Build Coastguard Worker Int64List* MtpDataPacket::getAInt64() {
219*ec779b8eSAndroid Build Coastguard Worker     uint32_t count;
220*ec779b8eSAndroid Build Coastguard Worker     if (!getUInt32(count))
221*ec779b8eSAndroid Build Coastguard Worker         return NULL;
222*ec779b8eSAndroid Build Coastguard Worker     Int64List* result = new Int64List;
223*ec779b8eSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < count; i++) {
224*ec779b8eSAndroid Build Coastguard Worker         int64_t value;
225*ec779b8eSAndroid Build Coastguard Worker         if (!getInt64(value)) {
226*ec779b8eSAndroid Build Coastguard Worker             delete result;
227*ec779b8eSAndroid Build Coastguard Worker             return NULL;
228*ec779b8eSAndroid Build Coastguard Worker         }
229*ec779b8eSAndroid Build Coastguard Worker         result->push_back(value);
230*ec779b8eSAndroid Build Coastguard Worker     }
231*ec779b8eSAndroid Build Coastguard Worker     return result;
232*ec779b8eSAndroid Build Coastguard Worker }
233*ec779b8eSAndroid Build Coastguard Worker 
getAUInt64()234*ec779b8eSAndroid Build Coastguard Worker UInt64List* MtpDataPacket::getAUInt64() {
235*ec779b8eSAndroid Build Coastguard Worker     uint32_t count;
236*ec779b8eSAndroid Build Coastguard Worker     if (!getUInt32(count))
237*ec779b8eSAndroid Build Coastguard Worker         return NULL;
238*ec779b8eSAndroid Build Coastguard Worker     UInt64List* result = new UInt64List;
239*ec779b8eSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < count; i++) {
240*ec779b8eSAndroid Build Coastguard Worker         uint64_t value;
241*ec779b8eSAndroid Build Coastguard Worker         if (!getUInt64(value)) {
242*ec779b8eSAndroid Build Coastguard Worker             delete result;
243*ec779b8eSAndroid Build Coastguard Worker             return NULL;
244*ec779b8eSAndroid Build Coastguard Worker         }
245*ec779b8eSAndroid Build Coastguard Worker         result->push_back(value);
246*ec779b8eSAndroid Build Coastguard Worker     }
247*ec779b8eSAndroid Build Coastguard Worker     return result;
248*ec779b8eSAndroid Build Coastguard Worker }
249*ec779b8eSAndroid Build Coastguard Worker 
putInt8(int8_t value)250*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putInt8(int8_t value) {
251*ec779b8eSAndroid Build Coastguard Worker     allocate(mOffset + 1);
252*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)value;
253*ec779b8eSAndroid Build Coastguard Worker     if (mPacketSize < mOffset)
254*ec779b8eSAndroid Build Coastguard Worker         mPacketSize = mOffset;
255*ec779b8eSAndroid Build Coastguard Worker }
256*ec779b8eSAndroid Build Coastguard Worker 
putUInt8(uint8_t value)257*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putUInt8(uint8_t value) {
258*ec779b8eSAndroid Build Coastguard Worker     allocate(mOffset + 1);
259*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)value;
260*ec779b8eSAndroid Build Coastguard Worker     if (mPacketSize < mOffset)
261*ec779b8eSAndroid Build Coastguard Worker         mPacketSize = mOffset;
262*ec779b8eSAndroid Build Coastguard Worker }
263*ec779b8eSAndroid Build Coastguard Worker 
putInt16(int16_t value)264*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putInt16(int16_t value) {
265*ec779b8eSAndroid Build Coastguard Worker     allocate(mOffset + 2);
266*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
267*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
268*ec779b8eSAndroid Build Coastguard Worker     if (mPacketSize < mOffset)
269*ec779b8eSAndroid Build Coastguard Worker         mPacketSize = mOffset;
270*ec779b8eSAndroid Build Coastguard Worker }
271*ec779b8eSAndroid Build Coastguard Worker 
putUInt16(uint16_t value)272*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putUInt16(uint16_t value) {
273*ec779b8eSAndroid Build Coastguard Worker     allocate(mOffset + 2);
274*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
275*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
276*ec779b8eSAndroid Build Coastguard Worker     if (mPacketSize < mOffset)
277*ec779b8eSAndroid Build Coastguard Worker         mPacketSize = mOffset;
278*ec779b8eSAndroid Build Coastguard Worker }
279*ec779b8eSAndroid Build Coastguard Worker 
putInt32(int32_t value)280*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putInt32(int32_t value) {
281*ec779b8eSAndroid Build Coastguard Worker     allocate(mOffset + 4);
282*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
283*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
284*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
285*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
286*ec779b8eSAndroid Build Coastguard Worker     if (mPacketSize < mOffset)
287*ec779b8eSAndroid Build Coastguard Worker         mPacketSize = mOffset;
288*ec779b8eSAndroid Build Coastguard Worker }
289*ec779b8eSAndroid Build Coastguard Worker 
putUInt32(uint32_t value)290*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putUInt32(uint32_t value) {
291*ec779b8eSAndroid Build Coastguard Worker     allocate(mOffset + 4);
292*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
293*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
294*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
295*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
296*ec779b8eSAndroid Build Coastguard Worker     if (mPacketSize < mOffset)
297*ec779b8eSAndroid Build Coastguard Worker         mPacketSize = mOffset;
298*ec779b8eSAndroid Build Coastguard Worker }
299*ec779b8eSAndroid Build Coastguard Worker 
putInt64(int64_t value)300*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putInt64(int64_t value) {
301*ec779b8eSAndroid Build Coastguard Worker     allocate(mOffset + 8);
302*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
303*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
304*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
305*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
306*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF);
307*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF);
308*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF);
309*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF);
310*ec779b8eSAndroid Build Coastguard Worker     if (mPacketSize < mOffset)
311*ec779b8eSAndroid Build Coastguard Worker         mPacketSize = mOffset;
312*ec779b8eSAndroid Build Coastguard Worker }
313*ec779b8eSAndroid Build Coastguard Worker 
putUInt64(uint64_t value)314*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putUInt64(uint64_t value) {
315*ec779b8eSAndroid Build Coastguard Worker     allocate(mOffset + 8);
316*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
317*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
318*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
319*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
320*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF);
321*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF);
322*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF);
323*ec779b8eSAndroid Build Coastguard Worker     mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF);
324*ec779b8eSAndroid Build Coastguard Worker     if (mPacketSize < mOffset)
325*ec779b8eSAndroid Build Coastguard Worker         mPacketSize = mOffset;
326*ec779b8eSAndroid Build Coastguard Worker }
327*ec779b8eSAndroid Build Coastguard Worker 
putInt128(const int128_t & value)328*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putInt128(const int128_t& value) {
329*ec779b8eSAndroid Build Coastguard Worker     putInt32(value[0]);
330*ec779b8eSAndroid Build Coastguard Worker     putInt32(value[1]);
331*ec779b8eSAndroid Build Coastguard Worker     putInt32(value[2]);
332*ec779b8eSAndroid Build Coastguard Worker     putInt32(value[3]);
333*ec779b8eSAndroid Build Coastguard Worker }
334*ec779b8eSAndroid Build Coastguard Worker 
putUInt128(const uint128_t & value)335*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putUInt128(const uint128_t& value) {
336*ec779b8eSAndroid Build Coastguard Worker     putUInt32(value[0]);
337*ec779b8eSAndroid Build Coastguard Worker     putUInt32(value[1]);
338*ec779b8eSAndroid Build Coastguard Worker     putUInt32(value[2]);
339*ec779b8eSAndroid Build Coastguard Worker     putUInt32(value[3]);
340*ec779b8eSAndroid Build Coastguard Worker }
341*ec779b8eSAndroid Build Coastguard Worker 
putInt128(int64_t value)342*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putInt128(int64_t value) {
343*ec779b8eSAndroid Build Coastguard Worker     putInt64(value);
344*ec779b8eSAndroid Build Coastguard Worker     putInt64(value < 0 ? -1 : 0);
345*ec779b8eSAndroid Build Coastguard Worker }
346*ec779b8eSAndroid Build Coastguard Worker 
putUInt128(uint64_t value)347*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putUInt128(uint64_t value) {
348*ec779b8eSAndroid Build Coastguard Worker     putUInt64(value);
349*ec779b8eSAndroid Build Coastguard Worker     putUInt64(0);
350*ec779b8eSAndroid Build Coastguard Worker }
351*ec779b8eSAndroid Build Coastguard Worker 
putAInt8(const int8_t * values,int count)352*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putAInt8(const int8_t* values, int count) {
353*ec779b8eSAndroid Build Coastguard Worker     putUInt32(count);
354*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < count; i++)
355*ec779b8eSAndroid Build Coastguard Worker         putInt8(*values++);
356*ec779b8eSAndroid Build Coastguard Worker }
357*ec779b8eSAndroid Build Coastguard Worker 
putAUInt8(const uint8_t * values,int count)358*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putAUInt8(const uint8_t* values, int count) {
359*ec779b8eSAndroid Build Coastguard Worker     putUInt32(count);
360*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < count; i++)
361*ec779b8eSAndroid Build Coastguard Worker         putUInt8(*values++);
362*ec779b8eSAndroid Build Coastguard Worker }
363*ec779b8eSAndroid Build Coastguard Worker 
putAInt16(const int16_t * values,int count)364*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putAInt16(const int16_t* values, int count) {
365*ec779b8eSAndroid Build Coastguard Worker     putUInt32(count);
366*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < count; i++)
367*ec779b8eSAndroid Build Coastguard Worker         putInt16(*values++);
368*ec779b8eSAndroid Build Coastguard Worker }
369*ec779b8eSAndroid Build Coastguard Worker 
putAUInt16(const uint16_t * values,int count)370*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putAUInt16(const uint16_t* values, int count) {
371*ec779b8eSAndroid Build Coastguard Worker     putUInt32(count);
372*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < count; i++)
373*ec779b8eSAndroid Build Coastguard Worker         putUInt16(*values++);
374*ec779b8eSAndroid Build Coastguard Worker }
375*ec779b8eSAndroid Build Coastguard Worker 
putAUInt16(const UInt16List * values)376*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putAUInt16(const UInt16List* values) {
377*ec779b8eSAndroid Build Coastguard Worker     size_t count = (values ? values->size() : 0);
378*ec779b8eSAndroid Build Coastguard Worker     putUInt32(count);
379*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < count; i++)
380*ec779b8eSAndroid Build Coastguard Worker         putUInt16((*values)[i]);
381*ec779b8eSAndroid Build Coastguard Worker }
382*ec779b8eSAndroid Build Coastguard Worker 
putAInt32(const int32_t * values,int count)383*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putAInt32(const int32_t* values, int count) {
384*ec779b8eSAndroid Build Coastguard Worker     putUInt32(count);
385*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < count; i++)
386*ec779b8eSAndroid Build Coastguard Worker         putInt32(*values++);
387*ec779b8eSAndroid Build Coastguard Worker }
388*ec779b8eSAndroid Build Coastguard Worker 
putAUInt32(const uint32_t * values,int count)389*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putAUInt32(const uint32_t* values, int count) {
390*ec779b8eSAndroid Build Coastguard Worker     putUInt32(count);
391*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < count; i++)
392*ec779b8eSAndroid Build Coastguard Worker         putUInt32(*values++);
393*ec779b8eSAndroid Build Coastguard Worker }
394*ec779b8eSAndroid Build Coastguard Worker 
putAUInt32(const UInt32List * list)395*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putAUInt32(const UInt32List* list) {
396*ec779b8eSAndroid Build Coastguard Worker     if (!list) {
397*ec779b8eSAndroid Build Coastguard Worker         putEmptyArray();
398*ec779b8eSAndroid Build Coastguard Worker     } else {
399*ec779b8eSAndroid Build Coastguard Worker         size_t size = list->size();
400*ec779b8eSAndroid Build Coastguard Worker         putUInt32(size);
401*ec779b8eSAndroid Build Coastguard Worker         for (size_t i = 0; i < size; i++)
402*ec779b8eSAndroid Build Coastguard Worker             putUInt32((*list)[i]);
403*ec779b8eSAndroid Build Coastguard Worker     }
404*ec779b8eSAndroid Build Coastguard Worker }
405*ec779b8eSAndroid Build Coastguard Worker 
putAInt64(const int64_t * values,int count)406*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putAInt64(const int64_t* values, int count) {
407*ec779b8eSAndroid Build Coastguard Worker     putUInt32(count);
408*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < count; i++)
409*ec779b8eSAndroid Build Coastguard Worker         putInt64(*values++);
410*ec779b8eSAndroid Build Coastguard Worker }
411*ec779b8eSAndroid Build Coastguard Worker 
putAUInt64(const uint64_t * values,int count)412*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putAUInt64(const uint64_t* values, int count) {
413*ec779b8eSAndroid Build Coastguard Worker     putUInt32(count);
414*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < count; i++)
415*ec779b8eSAndroid Build Coastguard Worker         putUInt64(*values++);
416*ec779b8eSAndroid Build Coastguard Worker }
417*ec779b8eSAndroid Build Coastguard Worker 
putString(const MtpStringBuffer & string)418*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putString(const MtpStringBuffer& string) {
419*ec779b8eSAndroid Build Coastguard Worker     string.writeToPacket(this);
420*ec779b8eSAndroid Build Coastguard Worker }
421*ec779b8eSAndroid Build Coastguard Worker 
putString(const char * s)422*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putString(const char* s) {
423*ec779b8eSAndroid Build Coastguard Worker     if (s != NULL) {
424*ec779b8eSAndroid Build Coastguard Worker         MtpStringBuffer string(s);
425*ec779b8eSAndroid Build Coastguard Worker         string.writeToPacket(this);
426*ec779b8eSAndroid Build Coastguard Worker     }
427*ec779b8eSAndroid Build Coastguard Worker }
428*ec779b8eSAndroid Build Coastguard Worker 
putString(const uint16_t * string)429*ec779b8eSAndroid Build Coastguard Worker void MtpDataPacket::putString(const uint16_t* string) {
430*ec779b8eSAndroid Build Coastguard Worker     if (string == NULL) {
431*ec779b8eSAndroid Build Coastguard Worker         return;
432*ec779b8eSAndroid Build Coastguard Worker     }
433*ec779b8eSAndroid Build Coastguard Worker     int count = 0;
434*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i <= MTP_STRING_MAX_CHARACTER_NUMBER; i++) {
435*ec779b8eSAndroid Build Coastguard Worker         if (string[i])
436*ec779b8eSAndroid Build Coastguard Worker             count++;
437*ec779b8eSAndroid Build Coastguard Worker         else
438*ec779b8eSAndroid Build Coastguard Worker             break;
439*ec779b8eSAndroid Build Coastguard Worker     }
440*ec779b8eSAndroid Build Coastguard Worker     putUInt8(count > 0 ? count + 1 : 0);
441*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < count; i++)
442*ec779b8eSAndroid Build Coastguard Worker         putUInt16(string[i]);
443*ec779b8eSAndroid Build Coastguard Worker     // only terminate with zero if string is not empty
444*ec779b8eSAndroid Build Coastguard Worker     if (count > 0)
445*ec779b8eSAndroid Build Coastguard Worker         putUInt16(0);
446*ec779b8eSAndroid Build Coastguard Worker }
447*ec779b8eSAndroid Build Coastguard Worker 
448*ec779b8eSAndroid Build Coastguard Worker #ifdef MTP_DEVICE
read(IMtpHandle * h)449*ec779b8eSAndroid Build Coastguard Worker int MtpDataPacket::read(IMtpHandle *h) {
450*ec779b8eSAndroid Build Coastguard Worker     int ret = h->read(mBuffer, MTP_BUFFER_SIZE);
451*ec779b8eSAndroid Build Coastguard Worker     if (ret < MTP_CONTAINER_HEADER_SIZE)
452*ec779b8eSAndroid Build Coastguard Worker         return -1;
453*ec779b8eSAndroid Build Coastguard Worker     mPacketSize = ret;
454*ec779b8eSAndroid Build Coastguard Worker     mOffset = MTP_CONTAINER_HEADER_SIZE;
455*ec779b8eSAndroid Build Coastguard Worker     return ret;
456*ec779b8eSAndroid Build Coastguard Worker }
457*ec779b8eSAndroid Build Coastguard Worker 
write(IMtpHandle * h)458*ec779b8eSAndroid Build Coastguard Worker int MtpDataPacket::write(IMtpHandle *h) {
459*ec779b8eSAndroid Build Coastguard Worker     MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
460*ec779b8eSAndroid Build Coastguard Worker     MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
461*ec779b8eSAndroid Build Coastguard Worker     int ret = h->write(mBuffer, mPacketSize);
462*ec779b8eSAndroid Build Coastguard Worker     return (ret < 0 ? ret : 0);
463*ec779b8eSAndroid Build Coastguard Worker }
464*ec779b8eSAndroid Build Coastguard Worker 
writeData(IMtpHandle * h,void * data,uint32_t length)465*ec779b8eSAndroid Build Coastguard Worker int MtpDataPacket::writeData(IMtpHandle *h, void* data, uint32_t length) {
466*ec779b8eSAndroid Build Coastguard Worker     allocate(length + MTP_CONTAINER_HEADER_SIZE);
467*ec779b8eSAndroid Build Coastguard Worker     memcpy(mBuffer + MTP_CONTAINER_HEADER_SIZE, data, length);
468*ec779b8eSAndroid Build Coastguard Worker     length += MTP_CONTAINER_HEADER_SIZE;
469*ec779b8eSAndroid Build Coastguard Worker     MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
470*ec779b8eSAndroid Build Coastguard Worker     MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
471*ec779b8eSAndroid Build Coastguard Worker     int ret = h->write(mBuffer, length);
472*ec779b8eSAndroid Build Coastguard Worker     return (ret < 0 ? ret : 0);
473*ec779b8eSAndroid Build Coastguard Worker }
474*ec779b8eSAndroid Build Coastguard Worker 
475*ec779b8eSAndroid Build Coastguard Worker #endif // MTP_DEVICE
476*ec779b8eSAndroid Build Coastguard Worker 
477*ec779b8eSAndroid Build Coastguard Worker #ifdef MTP_HOST
read(struct usb_request * request)478*ec779b8eSAndroid Build Coastguard Worker int MtpDataPacket::read(struct usb_request *request) {
479*ec779b8eSAndroid Build Coastguard Worker     // first read the header
480*ec779b8eSAndroid Build Coastguard Worker     request->buffer = mBuffer;
481*ec779b8eSAndroid Build Coastguard Worker     request->buffer_length = mBufferSize;
482*ec779b8eSAndroid Build Coastguard Worker     int length = transfer(request);
483*ec779b8eSAndroid Build Coastguard Worker     if (length >= MTP_CONTAINER_HEADER_SIZE) {
484*ec779b8eSAndroid Build Coastguard Worker         // look at the length field to see if the data spans multiple packets
485*ec779b8eSAndroid Build Coastguard Worker         uint32_t totalLength = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
486*ec779b8eSAndroid Build Coastguard Worker         allocate(totalLength);
487*ec779b8eSAndroid Build Coastguard Worker         while (totalLength > static_cast<uint32_t>(length)) {
488*ec779b8eSAndroid Build Coastguard Worker             request->buffer = mBuffer + length;
489*ec779b8eSAndroid Build Coastguard Worker             request->buffer_length = totalLength - length;
490*ec779b8eSAndroid Build Coastguard Worker             int ret = transfer(request);
491*ec779b8eSAndroid Build Coastguard Worker             if (ret >= 0)
492*ec779b8eSAndroid Build Coastguard Worker                 length += ret;
493*ec779b8eSAndroid Build Coastguard Worker             else {
494*ec779b8eSAndroid Build Coastguard Worker                 length = ret;
495*ec779b8eSAndroid Build Coastguard Worker                 break;
496*ec779b8eSAndroid Build Coastguard Worker             }
497*ec779b8eSAndroid Build Coastguard Worker         }
498*ec779b8eSAndroid Build Coastguard Worker     }
499*ec779b8eSAndroid Build Coastguard Worker     if (length >= 0)
500*ec779b8eSAndroid Build Coastguard Worker         mPacketSize = length;
501*ec779b8eSAndroid Build Coastguard Worker     return length;
502*ec779b8eSAndroid Build Coastguard Worker }
503*ec779b8eSAndroid Build Coastguard Worker 
readData(struct usb_request * request,void * buffer,int length)504*ec779b8eSAndroid Build Coastguard Worker int MtpDataPacket::readData(struct usb_request *request, void* buffer, int length) {
505*ec779b8eSAndroid Build Coastguard Worker     int read = 0;
506*ec779b8eSAndroid Build Coastguard Worker     while (read < length) {
507*ec779b8eSAndroid Build Coastguard Worker         request->buffer = (char *)buffer + read;
508*ec779b8eSAndroid Build Coastguard Worker         request->buffer_length = length - read;
509*ec779b8eSAndroid Build Coastguard Worker         int ret = transfer(request);
510*ec779b8eSAndroid Build Coastguard Worker         if (ret < 0) {
511*ec779b8eSAndroid Build Coastguard Worker             return ret;
512*ec779b8eSAndroid Build Coastguard Worker         }
513*ec779b8eSAndroid Build Coastguard Worker         read += ret;
514*ec779b8eSAndroid Build Coastguard Worker     }
515*ec779b8eSAndroid Build Coastguard Worker     return read;
516*ec779b8eSAndroid Build Coastguard Worker }
517*ec779b8eSAndroid Build Coastguard Worker 
518*ec779b8eSAndroid Build Coastguard Worker // Queue a read request.  Call readDataWait to wait for result
readDataAsync(struct usb_request * req)519*ec779b8eSAndroid Build Coastguard Worker int MtpDataPacket::readDataAsync(struct usb_request *req) {
520*ec779b8eSAndroid Build Coastguard Worker     if (usb_request_queue(req)) {
521*ec779b8eSAndroid Build Coastguard Worker         ALOGE("usb_endpoint_queue failed, errno: %d", errno);
522*ec779b8eSAndroid Build Coastguard Worker         return -1;
523*ec779b8eSAndroid Build Coastguard Worker     }
524*ec779b8eSAndroid Build Coastguard Worker     return 0;
525*ec779b8eSAndroid Build Coastguard Worker }
526*ec779b8eSAndroid Build Coastguard Worker 
527*ec779b8eSAndroid Build Coastguard Worker // Wait for result of readDataAsync
readDataWait(struct usb_device * device)528*ec779b8eSAndroid Build Coastguard Worker int MtpDataPacket::readDataWait(struct usb_device *device) {
529*ec779b8eSAndroid Build Coastguard Worker     struct usb_request *req = usb_request_wait(device, -1);
530*ec779b8eSAndroid Build Coastguard Worker     return (req ? req->actual_length : -1);
531*ec779b8eSAndroid Build Coastguard Worker }
532*ec779b8eSAndroid Build Coastguard Worker 
readDataHeader(struct usb_request * request)533*ec779b8eSAndroid Build Coastguard Worker int MtpDataPacket::readDataHeader(struct usb_request *request) {
534*ec779b8eSAndroid Build Coastguard Worker     request->buffer = mBuffer;
535*ec779b8eSAndroid Build Coastguard Worker     request->buffer_length = request->max_packet_size;
536*ec779b8eSAndroid Build Coastguard Worker     int length = transfer(request);
537*ec779b8eSAndroid Build Coastguard Worker     if (length >= 0)
538*ec779b8eSAndroid Build Coastguard Worker         mPacketSize = length;
539*ec779b8eSAndroid Build Coastguard Worker     return length;
540*ec779b8eSAndroid Build Coastguard Worker }
541*ec779b8eSAndroid Build Coastguard Worker 
write(struct usb_request * request,UrbPacketDivisionMode divisionMode)542*ec779b8eSAndroid Build Coastguard Worker int MtpDataPacket::write(struct usb_request *request, UrbPacketDivisionMode divisionMode) {
543*ec779b8eSAndroid Build Coastguard Worker     if (mPacketSize < MTP_CONTAINER_HEADER_SIZE || mPacketSize > MTP_BUFFER_SIZE) {
544*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Illegal packet size.");
545*ec779b8eSAndroid Build Coastguard Worker         return -1;
546*ec779b8eSAndroid Build Coastguard Worker     }
547*ec779b8eSAndroid Build Coastguard Worker 
548*ec779b8eSAndroid Build Coastguard Worker     MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
549*ec779b8eSAndroid Build Coastguard Worker     MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
550*ec779b8eSAndroid Build Coastguard Worker 
551*ec779b8eSAndroid Build Coastguard Worker     size_t processedBytes = 0;
552*ec779b8eSAndroid Build Coastguard Worker     while (processedBytes < mPacketSize) {
553*ec779b8eSAndroid Build Coastguard Worker         const size_t write_size =
554*ec779b8eSAndroid Build Coastguard Worker                 processedBytes == 0 && divisionMode == FIRST_PACKET_ONLY_HEADER ?
555*ec779b8eSAndroid Build Coastguard Worker                         MTP_CONTAINER_HEADER_SIZE : mPacketSize - processedBytes;
556*ec779b8eSAndroid Build Coastguard Worker         request->buffer = mBuffer + processedBytes;
557*ec779b8eSAndroid Build Coastguard Worker         request->buffer_length = write_size;
558*ec779b8eSAndroid Build Coastguard Worker         const int result = transfer(request);
559*ec779b8eSAndroid Build Coastguard Worker         if (result < 0) {
560*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Failed to write bytes to the device.");
561*ec779b8eSAndroid Build Coastguard Worker             return -1;
562*ec779b8eSAndroid Build Coastguard Worker         }
563*ec779b8eSAndroid Build Coastguard Worker         processedBytes += result;
564*ec779b8eSAndroid Build Coastguard Worker     }
565*ec779b8eSAndroid Build Coastguard Worker 
566*ec779b8eSAndroid Build Coastguard Worker     return processedBytes == mPacketSize ? processedBytes : -1;
567*ec779b8eSAndroid Build Coastguard Worker }
568*ec779b8eSAndroid Build Coastguard Worker 
write(struct usb_request * request,UrbPacketDivisionMode divisionMode,int fd,size_t payloadSize)569*ec779b8eSAndroid Build Coastguard Worker int64_t MtpDataPacket::write(struct usb_request *request,
570*ec779b8eSAndroid Build Coastguard Worker                          UrbPacketDivisionMode divisionMode,
571*ec779b8eSAndroid Build Coastguard Worker                          int fd,
572*ec779b8eSAndroid Build Coastguard Worker                          size_t payloadSize) {
573*ec779b8eSAndroid Build Coastguard Worker     // Obtain the greatest multiple of minimum packet size that is not greater than
574*ec779b8eSAndroid Build Coastguard Worker     // MTP_BUFFER_SIZE.
575*ec779b8eSAndroid Build Coastguard Worker     if (request->max_packet_size <= 0) {
576*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Cannot determine bulk transfer size due to illegal max packet size %d.",
577*ec779b8eSAndroid Build Coastguard Worker               request->max_packet_size);
578*ec779b8eSAndroid Build Coastguard Worker         return -1;
579*ec779b8eSAndroid Build Coastguard Worker     }
580*ec779b8eSAndroid Build Coastguard Worker     const size_t maxBulkTransferSize =
581*ec779b8eSAndroid Build Coastguard Worker             MTP_BUFFER_SIZE - (MTP_BUFFER_SIZE % request->max_packet_size);
582*ec779b8eSAndroid Build Coastguard Worker     const size_t containerLength = payloadSize + MTP_CONTAINER_HEADER_SIZE;
583*ec779b8eSAndroid Build Coastguard Worker     size_t processedBytes = 0;
584*ec779b8eSAndroid Build Coastguard Worker     bool readError = false;
585*ec779b8eSAndroid Build Coastguard Worker 
586*ec779b8eSAndroid Build Coastguard Worker     // Bind the packet with given request.
587*ec779b8eSAndroid Build Coastguard Worker     request->buffer = mBuffer;
588*ec779b8eSAndroid Build Coastguard Worker     allocate(maxBulkTransferSize);
589*ec779b8eSAndroid Build Coastguard Worker 
590*ec779b8eSAndroid Build Coastguard Worker     while (processedBytes < containerLength) {
591*ec779b8eSAndroid Build Coastguard Worker         size_t bulkTransferSize = 0;
592*ec779b8eSAndroid Build Coastguard Worker 
593*ec779b8eSAndroid Build Coastguard Worker         // prepare header.
594*ec779b8eSAndroid Build Coastguard Worker         const bool headerSent = processedBytes != 0;
595*ec779b8eSAndroid Build Coastguard Worker         if (!headerSent) {
596*ec779b8eSAndroid Build Coastguard Worker             MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, containerLength);
597*ec779b8eSAndroid Build Coastguard Worker             MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
598*ec779b8eSAndroid Build Coastguard Worker             bulkTransferSize += MTP_CONTAINER_HEADER_SIZE;
599*ec779b8eSAndroid Build Coastguard Worker         }
600*ec779b8eSAndroid Build Coastguard Worker 
601*ec779b8eSAndroid Build Coastguard Worker         // Prepare payload.
602*ec779b8eSAndroid Build Coastguard Worker         if (headerSent || divisionMode == FIRST_PACKET_HAS_PAYLOAD) {
603*ec779b8eSAndroid Build Coastguard Worker             const size_t processedPayloadBytes =
604*ec779b8eSAndroid Build Coastguard Worker                     headerSent ? processedBytes - MTP_CONTAINER_HEADER_SIZE : 0;
605*ec779b8eSAndroid Build Coastguard Worker             const size_t maxRead = payloadSize - processedPayloadBytes;
606*ec779b8eSAndroid Build Coastguard Worker             const size_t maxWrite = maxBulkTransferSize - bulkTransferSize;
607*ec779b8eSAndroid Build Coastguard Worker             const size_t bulkTransferPayloadSize = std::min(maxRead, maxWrite);
608*ec779b8eSAndroid Build Coastguard Worker             // prepare payload.
609*ec779b8eSAndroid Build Coastguard Worker             if (!readError) {
610*ec779b8eSAndroid Build Coastguard Worker                 const ssize_t result = readExactBytes(
611*ec779b8eSAndroid Build Coastguard Worker                         fd,
612*ec779b8eSAndroid Build Coastguard Worker                         mBuffer + bulkTransferSize,
613*ec779b8eSAndroid Build Coastguard Worker                         bulkTransferPayloadSize);
614*ec779b8eSAndroid Build Coastguard Worker                 if (result < 0) {
615*ec779b8eSAndroid Build Coastguard Worker                     ALOGE("Found an error while reading data from FD. Send 0 data instead.");
616*ec779b8eSAndroid Build Coastguard Worker                     readError = true;
617*ec779b8eSAndroid Build Coastguard Worker                 }
618*ec779b8eSAndroid Build Coastguard Worker             }
619*ec779b8eSAndroid Build Coastguard Worker             if (readError) {
620*ec779b8eSAndroid Build Coastguard Worker                 memset(mBuffer + bulkTransferSize, 0, bulkTransferPayloadSize);
621*ec779b8eSAndroid Build Coastguard Worker             }
622*ec779b8eSAndroid Build Coastguard Worker             bulkTransferSize += bulkTransferPayloadSize;
623*ec779b8eSAndroid Build Coastguard Worker         }
624*ec779b8eSAndroid Build Coastguard Worker 
625*ec779b8eSAndroid Build Coastguard Worker         // Bulk transfer.
626*ec779b8eSAndroid Build Coastguard Worker         mPacketSize = bulkTransferSize;
627*ec779b8eSAndroid Build Coastguard Worker         request->buffer_length = bulkTransferSize;
628*ec779b8eSAndroid Build Coastguard Worker         const int result = transfer(request);
629*ec779b8eSAndroid Build Coastguard Worker         if (result != static_cast<ssize_t>(bulkTransferSize)) {
630*ec779b8eSAndroid Build Coastguard Worker             // Cannot recover writing error.
631*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Found an error while write data to MtpDevice.");
632*ec779b8eSAndroid Build Coastguard Worker             return -1;
633*ec779b8eSAndroid Build Coastguard Worker         }
634*ec779b8eSAndroid Build Coastguard Worker 
635*ec779b8eSAndroid Build Coastguard Worker         // Update variables.
636*ec779b8eSAndroid Build Coastguard Worker         processedBytes += bulkTransferSize;
637*ec779b8eSAndroid Build Coastguard Worker     }
638*ec779b8eSAndroid Build Coastguard Worker 
639*ec779b8eSAndroid Build Coastguard Worker     return readError ? -1 : processedBytes;
640*ec779b8eSAndroid Build Coastguard Worker }
641*ec779b8eSAndroid Build Coastguard Worker 
642*ec779b8eSAndroid Build Coastguard Worker #endif // MTP_HOST
643*ec779b8eSAndroid Build Coastguard Worker 
getData(int * outLength) const644*ec779b8eSAndroid Build Coastguard Worker void* MtpDataPacket::getData(int* outLength) const {
645*ec779b8eSAndroid Build Coastguard Worker     int length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
646*ec779b8eSAndroid Build Coastguard Worker     if (length > 0) {
647*ec779b8eSAndroid Build Coastguard Worker         void* result = malloc(length);
648*ec779b8eSAndroid Build Coastguard Worker         if (result) {
649*ec779b8eSAndroid Build Coastguard Worker             memcpy(result, mBuffer + MTP_CONTAINER_HEADER_SIZE, length);
650*ec779b8eSAndroid Build Coastguard Worker             *outLength = length;
651*ec779b8eSAndroid Build Coastguard Worker             return result;
652*ec779b8eSAndroid Build Coastguard Worker         }
653*ec779b8eSAndroid Build Coastguard Worker     }
654*ec779b8eSAndroid Build Coastguard Worker     *outLength = 0;
655*ec779b8eSAndroid Build Coastguard Worker     return NULL;
656*ec779b8eSAndroid Build Coastguard Worker }
657*ec779b8eSAndroid Build Coastguard Worker 
658*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
659