blob: e058a5aaa4d4c25aa2167911ce978430713001ec [file] [log] [blame]
Mike Lockwood5ed68d22010-05-25 19:08:48 -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
Mike Lockwooda6c490b2010-06-05 22:45:01 -040017#define LOG_TAG "MtpDevice"
Mike Lockwoodb14e5882010-06-29 18:11:52 -040018
19#include "MtpDebug.h"
20#include "MtpDevice.h"
21#include "MtpDeviceInfo.h"
22#include "MtpObjectInfo.h"
23#include "MtpProperty.h"
24#include "MtpStorageInfo.h"
25#include "MtpStringBuffer.h"
Mike Lockwood0cf89f22010-07-26 20:40:45 -040026#include "MtpUtils.h"
Mike Lockwooda6c490b2010-06-05 22:45:01 -040027
Mike Lockwood5ed68d22010-05-25 19:08:48 -040028#include <stdio.h>
29#include <stdlib.h>
30#include <sys/types.h>
31#include <sys/ioctl.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <errno.h>
Mike Lockwood0cf89f22010-07-26 20:40:45 -040035#include <endian.h>
Mike Lockwood5ed68d22010-05-25 19:08:48 -040036
37#include <usbhost/usbhost.h>
38
Mike Lockwood5ed68d22010-05-25 19:08:48 -040039namespace android {
40
41MtpDevice::MtpDevice(struct usb_device* device, int interface,
42 struct usb_endpoint *ep_in, struct usb_endpoint *ep_out,
43 struct usb_endpoint *ep_intr)
44 : mDevice(device),
45 mInterface(interface),
46 mEndpointIn(ep_in),
47 mEndpointOut(ep_out),
48 mEndpointIntr(ep_intr),
49 mDeviceInfo(NULL),
50 mID(usb_device_get_unique_id(device)),
51 mSessionID(0),
Mike Lockwoodf7454622010-12-09 18:34:18 -080052 mTransactionID(0),
53 mReceivedResponse(false)
Mike Lockwood5ed68d22010-05-25 19:08:48 -040054{
55}
56
57MtpDevice::~MtpDevice() {
58 close();
Mike Lockwooda6c490b2010-06-05 22:45:01 -040059 for (int i = 0; i < mDeviceProperties.size(); i++)
60 delete mDeviceProperties[i];
Mike Lockwood5ed68d22010-05-25 19:08:48 -040061}
62
63void MtpDevice::initialize() {
64 openSession();
65 mDeviceInfo = getDeviceInfo();
66 if (mDeviceInfo) {
Mike Lockwooda6c490b2010-06-05 22:45:01 -040067 if (mDeviceInfo->mDeviceProperties) {
68 int count = mDeviceInfo->mDeviceProperties->size();
69 for (int i = 0; i < count; i++) {
70 MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
71 MtpProperty* property = getDevicePropDesc(propCode);
Mike Lockwood0c7c7c72010-12-07 11:24:28 -080072 if (property)
Mike Lockwooda6c490b2010-06-05 22:45:01 -040073 mDeviceProperties.push(property);
Mike Lockwooda6c490b2010-06-05 22:45:01 -040074 }
75 }
Mike Lockwood5ed68d22010-05-25 19:08:48 -040076 }
77}
78
79void MtpDevice::close() {
80 if (mDevice) {
81 usb_device_release_interface(mDevice, mInterface);
82 usb_device_close(mDevice);
83 mDevice = NULL;
84 }
85}
86
Mike Lockwood0c7c7c72010-12-07 11:24:28 -080087void MtpDevice::print() {
88 if (mDeviceInfo) {
89 mDeviceInfo->print();
90
91 if (mDeviceInfo->mDeviceProperties) {
92 LOGI("***** DEVICE PROPERTIES *****\n");
93 int count = mDeviceInfo->mDeviceProperties->size();
94 for (int i = 0; i < count; i++) {
95 MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
96 MtpProperty* property = getDevicePropDesc(propCode);
97 if (property) {
98 property->print();
99 }
100 }
101 }
102 }
103
104 if (mDeviceInfo->mPlaybackFormats) {
105 LOGI("***** OBJECT PROPERTIES *****\n");
106 int count = mDeviceInfo->mPlaybackFormats->size();
107 for (int i = 0; i < count; i++) {
108 MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i];
109 LOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format));
110 MtpObjectPropertyList* props = getObjectPropsSupported(format);
111 if (props) {
112 for (int j = 0; j < props->size(); j++) {
113 MtpObjectProperty prop = (*props)[j];
Mike Lockwood99e393a2010-12-07 18:53:04 -0800114 MtpProperty* property = getObjectPropDesc(prop, format);
Mike Lockwood0c7c7c72010-12-07 11:24:28 -0800115 if (property)
116 property->print();
117 else
118 LOGE("could not fetch property: %s",
119 MtpDebug::getObjectPropCodeName(prop));
120 }
121 }
122 }
123 }
124}
125
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400126const char* MtpDevice::getDeviceName() {
127 if (mDevice)
128 return usb_device_get_name(mDevice);
129 else
130 return "???";
131}
132
133bool MtpDevice::openSession() {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400134 Mutex::Autolock autoLock(mMutex);
135
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400136 mSessionID = 0;
137 mTransactionID = 0;
138 MtpSessionID newSession = 1;
139 mRequest.reset();
140 mRequest.setParameter(1, newSession);
141 if (!sendRequest(MTP_OPERATION_OPEN_SESSION))
142 return false;
143 MtpResponseCode ret = readResponse();
144 if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN)
145 newSession = mResponse.getParameter(1);
146 else if (ret != MTP_RESPONSE_OK)
147 return false;
148
149 mSessionID = newSession;
150 mTransactionID = 1;
151 return true;
152}
153
154bool MtpDevice::closeSession() {
155 // FIXME
156 return true;
157}
158
159MtpDeviceInfo* MtpDevice::getDeviceInfo() {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400160 Mutex::Autolock autoLock(mMutex);
161
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400162 mRequest.reset();
163 if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO))
164 return NULL;
165 if (!readData())
166 return NULL;
167 MtpResponseCode ret = readResponse();
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400168 if (ret == MTP_RESPONSE_OK) {
169 MtpDeviceInfo* info = new MtpDeviceInfo;
170 info->read(mData);
171 return info;
172 }
173 return NULL;
174}
175
176MtpStorageIDList* MtpDevice::getStorageIDs() {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400177 Mutex::Autolock autoLock(mMutex);
178
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400179 mRequest.reset();
180 if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS))
181 return NULL;
182 if (!readData())
183 return NULL;
184 MtpResponseCode ret = readResponse();
185 if (ret == MTP_RESPONSE_OK) {
186 return mData.getAUInt32();
187 }
188 return NULL;
189}
190
191MtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400192 Mutex::Autolock autoLock(mMutex);
193
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400194 mRequest.reset();
195 mRequest.setParameter(1, storageID);
196 if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO))
197 return NULL;
198 if (!readData())
199 return NULL;
200 MtpResponseCode ret = readResponse();
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400201 if (ret == MTP_RESPONSE_OK) {
202 MtpStorageInfo* info = new MtpStorageInfo(storageID);
203 info->read(mData);
204 return info;
205 }
206 return NULL;
207}
208
209MtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
210 MtpObjectFormat format, MtpObjectHandle parent) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400211 Mutex::Autolock autoLock(mMutex);
212
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400213 mRequest.reset();
214 mRequest.setParameter(1, storageID);
215 mRequest.setParameter(2, format);
216 mRequest.setParameter(3, parent);
217 if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES))
218 return NULL;
219 if (!readData())
220 return NULL;
221 MtpResponseCode ret = readResponse();
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400222 if (ret == MTP_RESPONSE_OK) {
223 return mData.getAUInt32();
224 }
225 return NULL;
226}
227
228MtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400229 Mutex::Autolock autoLock(mMutex);
230
Mike Lockwood6afc41d2010-06-11 16:34:52 -0400231 // FIXME - we might want to add some caching here
232
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400233 mRequest.reset();
234 mRequest.setParameter(1, handle);
235 if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO))
236 return NULL;
237 if (!readData())
238 return NULL;
239 MtpResponseCode ret = readResponse();
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400240 if (ret == MTP_RESPONSE_OK) {
241 MtpObjectInfo* info = new MtpObjectInfo(handle);
242 info->read(mData);
243 return info;
244 }
245 return NULL;
246}
247
Mike Lockwood3e072b32010-06-10 16:34:20 -0400248void* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400249 Mutex::Autolock autoLock(mMutex);
250
Mike Lockwood3e072b32010-06-10 16:34:20 -0400251 mRequest.reset();
252 mRequest.setParameter(1, handle);
253 if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
254 MtpResponseCode ret = readResponse();
255 if (ret == MTP_RESPONSE_OK) {
256 return mData.getData(outLength);
257 }
258 }
259 outLength = 0;
260 return NULL;
Mike Lockwood6afc41d2010-06-11 16:34:52 -0400261}
Mike Lockwood3e072b32010-06-10 16:34:20 -0400262
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400263MtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) {
264 Mutex::Autolock autoLock(mMutex);
265
266 mRequest.reset();
267 MtpObjectHandle parent = info->mParent;
268 if (parent == 0)
269 parent = MTP_PARENT_ROOT;
270
271 mRequest.setParameter(1, info->mStorageID);
272 mRequest.setParameter(2, info->mParent);
273
274 mData.putUInt32(info->mStorageID);
275 mData.putUInt16(info->mFormat);
276 mData.putUInt16(info->mProtectionStatus);
277 mData.putUInt32(info->mCompressedSize);
278 mData.putUInt16(info->mThumbFormat);
279 mData.putUInt32(info->mThumbCompressedSize);
280 mData.putUInt32(info->mThumbPixWidth);
281 mData.putUInt32(info->mThumbPixHeight);
282 mData.putUInt32(info->mImagePixWidth);
283 mData.putUInt32(info->mImagePixHeight);
284 mData.putUInt32(info->mImagePixDepth);
285 mData.putUInt32(info->mParent);
286 mData.putUInt16(info->mAssociationType);
287 mData.putUInt32(info->mAssociationDesc);
288 mData.putUInt32(info->mSequenceNumber);
289 mData.putString(info->mName);
290
291 char created[100], modified[100];
292 formatDateTime(info->mDateCreated, created, sizeof(created));
293 formatDateTime(info->mDateModified, modified, sizeof(modified));
294
295 mData.putString(created);
296 mData.putString(modified);
297 if (info->mKeywords)
298 mData.putString(info->mKeywords);
299 else
300 mData.putEmptyString();
301
302 if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400303 MtpResponseCode ret = readResponse();
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400304 if (ret == MTP_RESPONSE_OK) {
305 info->mStorageID = mResponse.getParameter(1);
306 info->mParent = mResponse.getParameter(2);
307 info->mHandle = mResponse.getParameter(3);
308 return info->mHandle;
309 }
310 }
311 return (MtpObjectHandle)-1;
312}
313
314bool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) {
315 Mutex::Autolock autoLock(mMutex);
316
317 int remaining = info->mCompressedSize;
318 mRequest.reset();
319 mRequest.setParameter(1, info->mHandle);
320 if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400321 // send data header
322 writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
323
324 char buffer[65536];
325 while (remaining > 0) {
326 int count = read(srcFD, buffer, sizeof(buffer));
327 if (count > 0) {
328 int written = mData.write(mEndpointOut, buffer, count);
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400329 // FIXME check error
330 remaining -= count;
331 } else {
332 break;
333 }
334 }
335 }
336 MtpResponseCode ret = readResponse();
337 return (remaining == 0 && ret == MTP_RESPONSE_OK);
338}
339
Mike Lockwood6afc41d2010-06-11 16:34:52 -0400340bool MtpDevice::deleteObject(MtpObjectHandle handle) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400341 Mutex::Autolock autoLock(mMutex);
342
Mike Lockwood6afc41d2010-06-11 16:34:52 -0400343 mRequest.reset();
344 mRequest.setParameter(1, handle);
345 if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) {
346 MtpResponseCode ret = readResponse();
347 if (ret == MTP_RESPONSE_OK)
348 return true;
349 }
350 return false;
351}
352
353MtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) {
354 MtpObjectInfo* info = getObjectInfo(handle);
355 if (info)
356 return info->mParent;
357 else
358 return -1;
359}
360
361MtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) {
362 MtpObjectInfo* info = getObjectInfo(handle);
363 if (info)
364 return info->mStorageID;
365 else
366 return -1;
Mike Lockwood3e072b32010-06-10 16:34:20 -0400367}
368
Mike Lockwood98693f62010-12-07 10:58:56 -0800369MtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) {
370 Mutex::Autolock autoLock(mMutex);
371
372 mRequest.reset();
373 mRequest.setParameter(1, format);
374 if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED))
375 return NULL;
376 if (!readData())
377 return NULL;
378 MtpResponseCode ret = readResponse();
379 if (ret == MTP_RESPONSE_OK) {
380 return mData.getAUInt16();
381 }
382 return NULL;
383
384}
385
Mike Lockwooda6c490b2010-06-05 22:45:01 -0400386MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400387 Mutex::Autolock autoLock(mMutex);
388
Mike Lockwooda6c490b2010-06-05 22:45:01 -0400389 mRequest.reset();
390 mRequest.setParameter(1, code);
391 if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC))
392 return NULL;
393 if (!readData())
394 return NULL;
395 MtpResponseCode ret = readResponse();
396 if (ret == MTP_RESPONSE_OK) {
397 MtpProperty* property = new MtpProperty;
Mike Lockwoode3e76c42010-09-02 14:57:30 -0400398 property->read(mData);
Mike Lockwooda6c490b2010-06-05 22:45:01 -0400399 return property;
400 }
401 return NULL;
402}
403
Mike Lockwood99e393a2010-12-07 18:53:04 -0800404MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) {
Mike Lockwood98693f62010-12-07 10:58:56 -0800405 Mutex::Autolock autoLock(mMutex);
406
407 mRequest.reset();
408 mRequest.setParameter(1, code);
Mike Lockwood99e393a2010-12-07 18:53:04 -0800409 mRequest.setParameter(2, format);
Mike Lockwood98693f62010-12-07 10:58:56 -0800410 if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC))
411 return NULL;
412 if (!readData())
413 return NULL;
414 MtpResponseCode ret = readResponse();
415 if (ret == MTP_RESPONSE_OK) {
416 MtpProperty* property = new MtpProperty;
417 property->read(mData);
418 return property;
419 }
420 return NULL;
421}
422
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500423// reads the object's data and writes it to the specified file path
Mike Lockwood27afe3a2010-11-19 13:52:20 -0500424bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500425 LOGD("readObject: %s", destPath);
426 int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC);
427 if (fd < 0) {
428 LOGE("open failed for %s", destPath);
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400429 return false;
430 }
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400431
Mike Lockwood27afe3a2010-11-19 13:52:20 -0500432 fchown(fd, getuid(), group);
433 // set permissions
434 int mask = umask(0);
435 fchmod(fd, perm);
436 umask(mask);
437
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500438 Mutex::Autolock autoLock(mMutex);
439 bool result = false;
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400440
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500441 mRequest.reset();
442 mRequest.setParameter(1, handle);
443 if (sendRequest(MTP_OPERATION_GET_OBJECT)
444 && mData.readDataHeader(mEndpointIn)) {
445 uint32_t length = mData.getContainerLength();
446 if (length < MTP_CONTAINER_HEADER_SIZE)
447 goto fail;
448 length -= MTP_CONTAINER_HEADER_SIZE;
449 uint32_t remaining = length;
450
451 int initialDataLength = 0;
452 void* initialData = mData.getData(initialDataLength);
453 if (initialData) {
454 if (initialDataLength > 0) {
455 if (write(fd, initialData, initialDataLength) != initialDataLength)
456 goto fail;
457 remaining -= initialDataLength;
458 }
459 free(initialData);
460 }
461
462 // USB reads greater than 16K don't work
463 char buffer1[16384], buffer2[16384];
464 char* readBuffer = buffer1;
465 char* writeBuffer = NULL;
466 int writeLength = 0;
467
468 while (remaining > 0 || writeBuffer) {
469 if (remaining > 0) {
470 // queue up a read request
471 int readSize = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
472 if (mData.readDataAsync(mEndpointIn, readBuffer, readSize)) {
473 LOGE("readDataAsync failed");
474 goto fail;
475 }
476 } else {
477 readBuffer = NULL;
478 }
479
480 if (writeBuffer) {
481 // write previous buffer
482 if (write(fd, writeBuffer, writeLength) != writeLength) {
483 LOGE("write failed");
484 // wait for pending read before failing
485 if (readBuffer)
486 mData.readDataWait(mEndpointIn);
487 goto fail;
488 }
489 writeBuffer = NULL;
490 }
491
492 // wait for read to complete
493 if (readBuffer) {
494 int read = mData.readDataWait(mEndpointIn);
495 if (read < 0)
496 goto fail;
497
498 writeBuffer = readBuffer;
499 writeLength = read;
500 remaining -= read;
501 readBuffer = (readBuffer == buffer1 ? buffer2 : buffer1);
502 }
503 }
504
505 MtpResponseCode response = readResponse();
506 if (response == MTP_RESPONSE_OK)
507 result = true;
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400508 }
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500509
510fail:
511 ::close(fd);
512 return result;
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400513}
Mike Lockwooda6c490b2010-06-05 22:45:01 -0400514
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400515bool MtpDevice::sendRequest(MtpOperationCode operation) {
Mike Lockwoodf43c6412010-07-27 11:50:34 -0400516 LOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
Mike Lockwoodf7454622010-12-09 18:34:18 -0800517 mReceivedResponse = false;
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400518 mRequest.setOperationCode(operation);
519 if (mTransactionID > 0)
520 mRequest.setTransactionID(mTransactionID++);
521 int ret = mRequest.write(mEndpointOut);
522 mRequest.dump();
523 return (ret > 0);
524}
525
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400526bool MtpDevice::sendData() {
Mike Lockwoodf43c6412010-07-27 11:50:34 -0400527 LOGV("sendData\n");
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400528 mData.setOperationCode(mRequest.getOperationCode());
529 mData.setTransactionID(mRequest.getTransactionID());
530 int ret = mData.write(mEndpointOut);
531 mData.dump();
532 return (ret > 0);
533}
534
535bool MtpDevice::readData() {
536 mData.reset();
537 int ret = mData.read(mEndpointIn);
Mike Lockwoodf43c6412010-07-27 11:50:34 -0400538 LOGV("readData returned %d\n", ret);
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400539 if (ret >= MTP_CONTAINER_HEADER_SIZE) {
Mike Lockwoodf7454622010-12-09 18:34:18 -0800540 if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
541 LOGD("got response packet instead of data packet");
542 // we got a response packet rather than data
543 // copy it to mResponse
544 mResponse.copyFrom(mData);
545 mReceivedResponse = true;
546 return false;
547 }
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400548 mData.dump();
549 return true;
550 }
551 else {
Mike Lockwoodf43c6412010-07-27 11:50:34 -0400552 LOGV("readResponse failed\n");
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400553 return false;
554 }
555}
556
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400557bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
558 mData.setOperationCode(operation);
559 mData.setTransactionID(mRequest.getTransactionID());
560 return (!mData.writeDataHeader(mEndpointOut, dataLength));
561}
562
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400563MtpResponseCode MtpDevice::readResponse() {
Mike Lockwoodf43c6412010-07-27 11:50:34 -0400564 LOGV("readResponse\n");
Mike Lockwoodf7454622010-12-09 18:34:18 -0800565 if (mReceivedResponse) {
566 mReceivedResponse = false;
567 return mResponse.getResponseCode();
568 }
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400569 int ret = mResponse.read(mEndpointIn);
570 if (ret >= MTP_CONTAINER_HEADER_SIZE) {
571 mResponse.dump();
572 return mResponse.getResponseCode();
Mike Lockwoodf7454622010-12-09 18:34:18 -0800573 } else {
Mike Lockwooda6c490b2010-06-05 22:45:01 -0400574 LOGD("readResponse failed\n");
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400575 return -1;
576 }
577}
578
579} // namespace android