MtpDataPacket.cpp revision 1865a5ddcfe7b0e8dc211419aea1094b1491a5fd
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "MtpDataPacket"
18
19#include <stdio.h>
20#include <sys/types.h>
21#include <fcntl.h>
22
23#include "MtpDataPacket.h"
24#include "MtpStringBuffer.h"
25
26namespace android {
27
28MtpDataPacket::MtpDataPacket()
29    :   MtpPacket(512),
30        mOffset(MTP_CONTAINER_HEADER_SIZE)
31{
32}
33
34MtpDataPacket::~MtpDataPacket() {
35}
36
37void MtpDataPacket::reset() {
38    MtpPacket::reset();
39    mOffset = MTP_CONTAINER_HEADER_SIZE;
40}
41
42void MtpDataPacket::setOperationCode(MtpOperationCode code) {
43    MtpPacket::putUInt16(MTP_CONTAINER_CODE_OFFSET, code);
44}
45
46void MtpDataPacket::setTransactionID(MtpTransactionID id) {
47    MtpPacket::putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);
48}
49
50uint16_t MtpDataPacket::getUInt16() {
51    int offset = mOffset;
52    uint16_t result = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8);
53    mOffset += 2;
54    return result;
55}
56
57uint32_t MtpDataPacket::getUInt32() {
58    int offset = mOffset;
59    uint32_t result = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) |
60           ((uint32_t)mBuffer[offset + 2] << 16)  | ((uint32_t)mBuffer[offset + 3] << 24);
61    mOffset += 4;
62    return result;
63}
64
65uint64_t MtpDataPacket::getUInt64() {
66    int offset = mOffset;
67    uint64_t result = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) |
68           ((uint64_t)mBuffer[offset + 2] << 16) | ((uint64_t)mBuffer[offset + 3] << 24) |
69           ((uint64_t)mBuffer[offset + 4] << 32) | ((uint64_t)mBuffer[offset + 5] << 40) |
70           ((uint64_t)mBuffer[offset + 6] << 48)  | ((uint64_t)mBuffer[offset + 7] << 56);
71    mOffset += 8;
72    return result;
73}
74
75void MtpDataPacket::getUInt128(uint128_t& value) {
76    value[0] = getUInt32();
77    value[1] = getUInt32();
78    value[2] = getUInt32();
79    value[3] = getUInt32();
80}
81
82void MtpDataPacket::getString(MtpStringBuffer& string)
83{
84    string.readFromPacket(this);
85}
86
87Int8List* MtpDataPacket::getAInt8() {
88    Int8List* result = new Int8List;
89    int count = getUInt32();
90    for (int i = 0; i < count; i++)
91        result->push(getInt8());
92    return result;
93}
94
95UInt8List* MtpDataPacket::getAUInt8() {
96    UInt8List* result = new UInt8List;
97    int count = getUInt32();
98    for (int i = 0; i < count; i++)
99        result->push(getUInt8());
100    return result;
101}
102
103Int16List* MtpDataPacket::getAInt16() {
104    Int16List* result = new Int16List;
105    int count = getUInt32();
106    for (int i = 0; i < count; i++)
107        result->push(getInt16());
108    return result;
109}
110
111UInt16List* MtpDataPacket::getAUInt16() {
112    UInt16List* result = new UInt16List;
113    int count = getUInt32();
114    for (int i = 0; i < count; i++)
115        result->push(getUInt16());
116    return result;
117}
118
119Int32List* MtpDataPacket::getAInt32() {
120    Int32List* result = new Int32List;
121    int count = getUInt32();
122    for (int i = 0; i < count; i++)
123        result->push(getInt32());
124    return result;
125}
126
127UInt32List* MtpDataPacket::getAUInt32() {
128    UInt32List* result = new UInt32List;
129    int count = getUInt32();
130    for (int i = 0; i < count; i++)
131        result->push(getUInt32());
132    return result;
133}
134
135Int64List* MtpDataPacket::getAInt64() {
136    Int64List* result = new Int64List;
137    int count = getUInt32();
138    for (int i = 0; i < count; i++)
139        result->push(getInt64());
140    return result;
141}
142
143UInt64List* MtpDataPacket::getAUInt64() {
144    UInt64List* result = new UInt64List;
145    int count = getUInt32();
146    for (int i = 0; i < count; i++)
147        result->push(getUInt64());
148    return result;
149}
150
151void MtpDataPacket::putInt8(int8_t value) {
152    allocate(mOffset + 1);
153    mBuffer[mOffset++] = (uint8_t)value;
154    if (mPacketSize < mOffset)
155        mPacketSize = mOffset;
156}
157
158void MtpDataPacket::putUInt8(uint8_t value) {
159    allocate(mOffset + 1);
160    mBuffer[mOffset++] = (uint8_t)value;
161    if (mPacketSize < mOffset)
162        mPacketSize = mOffset;
163}
164
165void MtpDataPacket::putInt16(int16_t value) {
166    allocate(mOffset + 2);
167    mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
168    mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
169    if (mPacketSize < mOffset)
170        mPacketSize = mOffset;
171}
172
173void MtpDataPacket::putUInt16(uint16_t value) {
174    allocate(mOffset + 2);
175    mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
176    mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
177    if (mPacketSize < mOffset)
178        mPacketSize = mOffset;
179}
180
181void MtpDataPacket::putInt32(int32_t value) {
182    allocate(mOffset + 4);
183    mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
184    mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
185    mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
186    mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
187    if (mPacketSize < mOffset)
188        mPacketSize = mOffset;
189}
190
191void MtpDataPacket::putUInt32(uint32_t value) {
192    allocate(mOffset + 4);
193    mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
194    mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
195    mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
196    mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
197    if (mPacketSize < mOffset)
198        mPacketSize = mOffset;
199}
200
201void MtpDataPacket::putInt64(int64_t value) {
202    allocate(mOffset + 8);
203    mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
204    mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
205    mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
206    mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
207    mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF);
208    mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF);
209    mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF);
210    mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF);
211    if (mPacketSize < mOffset)
212        mPacketSize = mOffset;
213}
214
215void MtpDataPacket::putUInt64(uint64_t value) {
216    allocate(mOffset + 8);
217    mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
218    mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
219    mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
220    mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
221    mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF);
222    mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF);
223    mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF);
224    mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF);
225    if (mPacketSize < mOffset)
226        mPacketSize = mOffset;
227}
228
229void MtpDataPacket::putInt128(const int128_t& value) {
230    putInt32(value[0]);
231    putInt32(value[1]);
232    putInt32(value[2]);
233    putInt32(value[3]);
234}
235
236void MtpDataPacket::putUInt128(const uint128_t& value) {
237    putUInt32(value[0]);
238    putUInt32(value[1]);
239    putUInt32(value[2]);
240    putUInt32(value[3]);
241}
242
243void MtpDataPacket::putAInt8(const int8_t* values, int count) {
244    putUInt32(count);
245    for (int i = 0; i < count; i++)
246        putInt8(*values++);
247}
248
249void MtpDataPacket::putAUInt8(const uint8_t* values, int count) {
250    putUInt32(count);
251    for (int i = 0; i < count; i++)
252        putUInt8(*values++);
253}
254
255void MtpDataPacket::putAInt16(const int16_t* values, int count) {
256    putUInt32(count);
257    for (int i = 0; i < count; i++)
258        putInt16(*values++);
259}
260
261void MtpDataPacket::putAUInt16(const uint16_t* values, int count) {
262    putUInt32(count);
263    for (int i = 0; i < count; i++)
264        putUInt16(*values++);
265}
266
267void MtpDataPacket::putAInt32(const int32_t* values, int count) {
268    putUInt32(count);
269    for (int i = 0; i < count; i++)
270        putInt32(*values++);
271}
272
273void MtpDataPacket::putAUInt32(const uint32_t* values, int count) {
274    putUInt32(count);
275    for (int i = 0; i < count; i++)
276        putUInt32(*values++);
277}
278
279void MtpDataPacket::putAUInt32(const UInt32List* list) {
280    if (!list) {
281        putEmptyArray();
282    } else {
283        size_t size = list->size();
284        putUInt32(size);
285        for (size_t i = 0; i < size; i++)
286            putUInt32((*list)[i]);
287    }
288}
289
290void MtpDataPacket::putAInt64(const int64_t* values, int count) {
291    putUInt32(count);
292    for (int i = 0; i < count; i++)
293        putInt64(*values++);
294}
295
296void MtpDataPacket::putAUInt64(const uint64_t* values, int count) {
297    putUInt32(count);
298    for (int i = 0; i < count; i++)
299        putUInt64(*values++);
300}
301
302void MtpDataPacket::putString(const MtpStringBuffer& string) {
303    string.writeToPacket(this);
304}
305
306void MtpDataPacket::putString(const char* s) {
307    MtpStringBuffer string(s);
308    string.writeToPacket(this);
309}
310
311void MtpDataPacket::putString(const uint16_t* string) {
312    int count = 0;
313    for (int i = 0; i < 256; i++) {
314        if (string[i])
315            count++;
316        else
317            break;
318    }
319    putUInt8(count);
320    for (int i = 0; i < count; i++)
321        putUInt16(string[i]);
322}
323
324#ifdef MTP_DEVICE
325int MtpDataPacket::read(int fd) {
326    // first read the header
327    int ret = ::read(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
328    if (ret != MTP_CONTAINER_HEADER_SIZE)
329        return -1;
330    // then the following data
331    int total = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
332    int remaining = total - MTP_CONTAINER_HEADER_SIZE;
333    ret = ::read(fd, &mBuffer[0] + MTP_CONTAINER_HEADER_SIZE, remaining);
334    if (ret != remaining)
335        return -1;
336
337    mPacketSize = total;
338    mOffset = MTP_CONTAINER_HEADER_SIZE;
339    return total;
340}
341
342int MtpDataPacket::readDataHeader(int fd) {
343    int ret = ::read(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
344    if (ret > 0)
345        mPacketSize = ret;
346    else
347        mPacketSize = 0;
348    return ret;
349}
350
351int MtpDataPacket::write(int fd) {
352    MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
353    MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
354
355    // send header separately from data
356    int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
357    if (ret == MTP_CONTAINER_HEADER_SIZE)
358        ret = ::write(fd, mBuffer + MTP_CONTAINER_HEADER_SIZE,
359                        mPacketSize - MTP_CONTAINER_HEADER_SIZE);
360    return (ret < 0 ? ret : 0);
361}
362
363int MtpDataPacket::writeDataHeader(int fd, uint32_t length) {
364    MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
365    MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
366    int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
367    return (ret < 0 ? ret : 0);
368}
369#endif // MTP_DEVICE
370
371#ifdef MTP_HOST
372int MtpDataPacket::read(struct usb_endpoint *ep) {
373    // first read the header
374    int length = transfer(ep, mBuffer, mBufferSize);
375    if (length > MTP_CONTAINER_HEADER_SIZE) {
376        // look at the length field to see if the data spans multiple packets
377        uint32_t totalLength = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
378        while (totalLength > length) {
379            allocate(length + mAllocationIncrement);
380            int ret = transfer(ep, mBuffer + length, mAllocationIncrement);
381            if (ret >= 0)
382                length += ret;
383            else {
384                length = ret;
385                break;
386            }
387        }
388    }
389    if (length >= 0)
390        mPacketSize = length;
391    return length;
392}
393
394int MtpDataPacket::write(struct usb_endpoint *ep) {
395    MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
396    MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
397
398    // send header separately from data
399    int ret = transfer(ep, mBuffer, MTP_CONTAINER_HEADER_SIZE);
400    if (ret == MTP_CONTAINER_HEADER_SIZE)
401        ret = transfer(ep, mBuffer + MTP_CONTAINER_HEADER_SIZE,
402                        mPacketSize - MTP_CONTAINER_HEADER_SIZE);
403    return (ret < 0 ? ret : 0);
404}
405
406#endif // MTP_HOST
407
408void* MtpDataPacket::getData(int& outLength) const {
409    int length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
410    if (length > 0) {
411        void* result = malloc(length);
412        if (result) {
413            memcpy(result, mBuffer + MTP_CONTAINER_HEADER_SIZE, length);
414            outLength = length;
415            return result;
416        }
417    }
418    outLength = 0;
419    return NULL;
420}
421
422}  // namespace android
423