blob: 8e7ea6e78659e265abb9ac258ca6724866ddf21c [file] [log] [blame]
Mike Lockwood16864ba2010-05-11 17:16:59 -04001/*
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#include <stdio.h>
18#include <sys/types.h>
19#include <fcntl.h>
20
21#include "MtpDataPacket.h"
22#include "MtpStringBuffer.h"
23
24MtpDataPacket::MtpDataPacket()
25 : MtpPacket(512),
26 mOffset(MTP_CONTAINER_HEADER_SIZE)
27{
28}
29
30MtpDataPacket::~MtpDataPacket() {
31}
32
33void MtpDataPacket::reset() {
34 MtpPacket::reset();
35 mOffset = MTP_CONTAINER_HEADER_SIZE;
36}
37
38void MtpDataPacket::setOperationCode(MtpOperationCode code) {
39 MtpPacket::putUInt16(MTP_CONTAINER_CODE_OFFSET, code);
40}
41
42void MtpDataPacket::setTransactionID(MtpTransactionID id) {
43 MtpPacket::putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);
44}
45
46uint16_t MtpDataPacket::getUInt16() {
47 int offset = mOffset;
48 uint16_t result = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8);
49 mOffset += 2;
50 return result;
51}
52
53uint32_t MtpDataPacket::getUInt32() {
54 int offset = mOffset;
55 uint32_t result = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) |
56 ((uint32_t)mBuffer[offset + 2] << 16) | ((uint32_t)mBuffer[offset + 3] << 24);
57 mOffset += 4;
58 return result;
59}
60
61uint64_t MtpDataPacket::getUInt64() {
62 int offset = mOffset;
63 uint64_t result = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) |
64 ((uint64_t)mBuffer[offset + 2] << 16) | ((uint64_t)mBuffer[offset + 3] << 24) |
65 ((uint64_t)mBuffer[offset + 4] << 32) | ((uint64_t)mBuffer[offset + 5] << 40) |
66 ((uint64_t)mBuffer[offset + 6] << 48) | ((uint64_t)mBuffer[offset + 7] << 56);
67 mOffset += 8;
68 return result;
69}
70
71void MtpDataPacket::getString(MtpStringBuffer& string)
72{
73 string.readFromPacket(this);
74}
75
76void MtpDataPacket::putInt8(int8_t value) {
77 allocate(mOffset + 1);
78 mBuffer[mOffset++] = (uint8_t)value;
79 if (mPacketSize < mOffset)
80 mPacketSize = mOffset;
81}
82
83void MtpDataPacket::putUInt8(uint8_t value) {
84 allocate(mOffset + 1);
85 mBuffer[mOffset++] = (uint8_t)value;
86 if (mPacketSize < mOffset)
87 mPacketSize = mOffset;
88}
89
90void MtpDataPacket::putInt16(int16_t value) {
91 allocate(mOffset + 2);
92 mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
93 mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
94 if (mPacketSize < mOffset)
95 mPacketSize = mOffset;
96}
97
98void MtpDataPacket::putUInt16(uint16_t value) {
99 allocate(mOffset + 2);
100 mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
101 mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
102 if (mPacketSize < mOffset)
103 mPacketSize = mOffset;
104}
105
106void MtpDataPacket::putInt32(int32_t value) {
107 allocate(mOffset + 4);
108 mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
109 mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
110 mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
111 mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
112 if (mPacketSize < mOffset)
113 mPacketSize = mOffset;
114}
115
116void MtpDataPacket::putUInt32(uint32_t value) {
117 allocate(mOffset + 4);
118 mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
119 mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
120 mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
121 mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
122 if (mPacketSize < mOffset)
123 mPacketSize = mOffset;
124}
125
126void MtpDataPacket::putInt64(int64_t value) {
127 allocate(mOffset + 8);
128 mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
129 mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
130 mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
131 mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
132 mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF);
133 mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF);
134 mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF);
135 mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF);
136 if (mPacketSize < mOffset)
137 mPacketSize = mOffset;
138}
139
140void MtpDataPacket::putUInt64(uint64_t value) {
141 allocate(mOffset + 8);
142 mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
143 mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
144 mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
145 mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
146 mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF);
147 mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF);
148 mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF);
149 mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF);
150 if (mPacketSize < mOffset)
151 mPacketSize = mOffset;
152}
153
154void MtpDataPacket::putAInt8(const int8_t* values, int count) {
155 putUInt32(count);
156 for (int i = 0; i < count; i++)
157 putInt8(*values++);
158}
159
160void MtpDataPacket::putAUInt8(const uint8_t* values, int count) {
161 putUInt32(count);
162 for (int i = 0; i < count; i++)
163 putUInt8(*values++);
164}
165
166void MtpDataPacket::putAInt16(const int16_t* values, int count) {
167 putUInt32(count);
168 for (int i = 0; i < count; i++)
169 putInt16(*values++);
170}
171
172void MtpDataPacket::putAUInt16(const uint16_t* values, int count) {
173 putUInt32(count);
174 for (int i = 0; i < count; i++)
175 putUInt16(*values++);
176}
177
178void MtpDataPacket::putAInt32(const int32_t* values, int count) {
179 putUInt32(count);
180 for (int i = 0; i < count; i++)
181 putInt32(*values++);
182}
183
184void MtpDataPacket::putAUInt32(const uint32_t* values, int count) {
185 putUInt32(count);
186 for (int i = 0; i < count; i++)
187 putUInt32(*values++);
188}
189
190void MtpDataPacket::putAUInt32(const UInt32List* list) {
191 if (!list) {
192 putEmptyArray();
193 } else {
194 size_t size = list->size();
195 putUInt32(size);
196 for (size_t i = 0; i < size; i++)
197 putUInt32((*list)[i]);
198 }
199}
200
201void MtpDataPacket::putAInt64(const int64_t* values, int count) {
202 putUInt32(count);
203 for (int i = 0; i < count; i++)
204 putInt64(*values++);
205}
206
207void MtpDataPacket::putAUInt64(const uint64_t* values, int count) {
208 putUInt32(count);
209 for (int i = 0; i < count; i++)
210 putUInt64(*values++);
211}
212
213void MtpDataPacket::putString(const MtpStringBuffer& string)
214{
215 string.writeToPacket(this);
216}
217
218void MtpDataPacket::putString(const char* s)
219{
220 MtpStringBuffer string(s);
221 string.writeToPacket(this);
222}
223
224#ifdef MTP_DEVICE
225int MtpDataPacket::read(int fd) {
226 // first read the header
227 int ret = ::read(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
228printf("MtpDataPacket::read 1 returned %d\n", ret);
229 if (ret != MTP_CONTAINER_HEADER_SIZE)
230 return -1;
231 // then the following data
232 int total = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
233 int remaining = total - MTP_CONTAINER_HEADER_SIZE;
234printf("total: %d, remaining: %d\n", total, remaining);
235 ret = ::read(fd, &mBuffer[0] + MTP_CONTAINER_HEADER_SIZE, remaining);
236printf("MtpDataPacket::read 2 returned %d\n", ret);
237 if (ret != remaining)
238 return -1;
239
240 mPacketSize = total;
241 mOffset = MTP_CONTAINER_HEADER_SIZE;
242 return total;
243}
244
245int MtpDataPacket::readDataHeader(int fd) {
246 int ret = ::read(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
247 if (ret > 0)
248 mPacketSize = ret;
249 else
250 mPacketSize = 0;
251 return ret;
252}
253
254int MtpDataPacket::write(int fd) {
255 MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
256 MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
257
258 // send header separately from data
259 int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
260 if (ret == MTP_CONTAINER_HEADER_SIZE)
261 ret = ::write(fd, mBuffer + MTP_CONTAINER_HEADER_SIZE,
262 mPacketSize - MTP_CONTAINER_HEADER_SIZE);
263 return (ret < 0 ? ret : 0);
264}
265
266int MtpDataPacket::writeDataHeader(int fd, uint32_t length) {
267 MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
268 MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
269 int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
270 return (ret < 0 ? ret : 0);
271}
272#endif // MTP_DEVICE
273
274#ifdef MTP_HOST
275int MtpDataPacket::read(struct usb_endpoint *ep) {
276 // first read the header
277 int ret = transfer(ep, mBuffer, mBufferSize);
278printf("MtpDataPacket::transfer returned %d\n", ret);
279 if (ret >= 0)
280 mPacketSize = ret;
281 return ret;
282}
283
284int MtpDataPacket::write(struct usb_endpoint *ep) {
285 MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
286 MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
287
288 // send header separately from data
289 int ret = transfer(ep, mBuffer, MTP_CONTAINER_HEADER_SIZE);
290 if (ret == MTP_CONTAINER_HEADER_SIZE)
291 ret = transfer(ep, mBuffer + MTP_CONTAINER_HEADER_SIZE,
292 mPacketSize - MTP_CONTAINER_HEADER_SIZE);
293 return (ret < 0 ? ret : 0);
294}
295
296#endif // MTP_HOST