blob: d22c72fc4c6a8637ca11a1bbd332fe31fce0b08c [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,
Mike Lockwood42d0b792011-01-04 14:48:57 -050042 const struct usb_endpoint_descriptor *ep_in,
43 const struct usb_endpoint_descriptor *ep_out,
44 const struct usb_endpoint_descriptor *ep_intr)
Mike Lockwood5ed68d22010-05-25 19:08:48 -040045 : mDevice(device),
46 mInterface(interface),
Mike Lockwood42d0b792011-01-04 14:48:57 -050047 mRequestIn1(NULL),
48 mRequestIn2(NULL),
49 mRequestOut(NULL),
50 mRequestIntr(NULL),
Mike Lockwood5ed68d22010-05-25 19:08:48 -040051 mDeviceInfo(NULL),
52 mID(usb_device_get_unique_id(device)),
53 mSessionID(0),
Mike Lockwoodf7454622010-12-09 18:34:18 -080054 mTransactionID(0),
55 mReceivedResponse(false)
Mike Lockwood5ed68d22010-05-25 19:08:48 -040056{
Mike Lockwood42d0b792011-01-04 14:48:57 -050057 mRequestIn1 = usb_request_new(device, ep_in);
58 mRequestIn2 = usb_request_new(device, ep_in);
59 mRequestOut = usb_request_new(device, ep_out);
60 mRequestIntr = usb_request_new(device, ep_intr);
Mike Lockwood5ed68d22010-05-25 19:08:48 -040061}
62
63MtpDevice::~MtpDevice() {
64 close();
Mike Lockwooda6c490b2010-06-05 22:45:01 -040065 for (int i = 0; i < mDeviceProperties.size(); i++)
66 delete mDeviceProperties[i];
Mike Lockwood42d0b792011-01-04 14:48:57 -050067 usb_request_free(mRequestIn1);
68 usb_request_free(mRequestIn2);
69 usb_request_free(mRequestOut);
70 usb_request_free(mRequestIntr);
Mike Lockwood5ed68d22010-05-25 19:08:48 -040071}
72
73void MtpDevice::initialize() {
74 openSession();
75 mDeviceInfo = getDeviceInfo();
76 if (mDeviceInfo) {
Mike Lockwooda6c490b2010-06-05 22:45:01 -040077 if (mDeviceInfo->mDeviceProperties) {
78 int count = mDeviceInfo->mDeviceProperties->size();
79 for (int i = 0; i < count; i++) {
80 MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
81 MtpProperty* property = getDevicePropDesc(propCode);
Mike Lockwood0c7c7c72010-12-07 11:24:28 -080082 if (property)
Mike Lockwooda6c490b2010-06-05 22:45:01 -040083 mDeviceProperties.push(property);
Mike Lockwooda6c490b2010-06-05 22:45:01 -040084 }
85 }
Mike Lockwood5ed68d22010-05-25 19:08:48 -040086 }
87}
88
89void MtpDevice::close() {
90 if (mDevice) {
91 usb_device_release_interface(mDevice, mInterface);
92 usb_device_close(mDevice);
93 mDevice = NULL;
94 }
95}
96
Mike Lockwood0c7c7c72010-12-07 11:24:28 -080097void MtpDevice::print() {
98 if (mDeviceInfo) {
99 mDeviceInfo->print();
100
101 if (mDeviceInfo->mDeviceProperties) {
102 LOGI("***** DEVICE PROPERTIES *****\n");
103 int count = mDeviceInfo->mDeviceProperties->size();
104 for (int i = 0; i < count; i++) {
105 MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
106 MtpProperty* property = getDevicePropDesc(propCode);
107 if (property) {
108 property->print();
109 }
110 }
111 }
112 }
113
114 if (mDeviceInfo->mPlaybackFormats) {
115 LOGI("***** OBJECT PROPERTIES *****\n");
116 int count = mDeviceInfo->mPlaybackFormats->size();
117 for (int i = 0; i < count; i++) {
118 MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i];
119 LOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format));
120 MtpObjectPropertyList* props = getObjectPropsSupported(format);
121 if (props) {
122 for (int j = 0; j < props->size(); j++) {
123 MtpObjectProperty prop = (*props)[j];
Mike Lockwood99e393a2010-12-07 18:53:04 -0800124 MtpProperty* property = getObjectPropDesc(prop, format);
Mike Lockwood0c7c7c72010-12-07 11:24:28 -0800125 if (property)
126 property->print();
127 else
128 LOGE("could not fetch property: %s",
129 MtpDebug::getObjectPropCodeName(prop));
130 }
131 }
132 }
133 }
134}
135
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400136const char* MtpDevice::getDeviceName() {
137 if (mDevice)
138 return usb_device_get_name(mDevice);
139 else
140 return "???";
141}
142
143bool MtpDevice::openSession() {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400144 Mutex::Autolock autoLock(mMutex);
145
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400146 mSessionID = 0;
147 mTransactionID = 0;
148 MtpSessionID newSession = 1;
149 mRequest.reset();
150 mRequest.setParameter(1, newSession);
151 if (!sendRequest(MTP_OPERATION_OPEN_SESSION))
152 return false;
153 MtpResponseCode ret = readResponse();
154 if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN)
155 newSession = mResponse.getParameter(1);
156 else if (ret != MTP_RESPONSE_OK)
157 return false;
158
159 mSessionID = newSession;
160 mTransactionID = 1;
161 return true;
162}
163
164bool MtpDevice::closeSession() {
165 // FIXME
166 return true;
167}
168
169MtpDeviceInfo* MtpDevice::getDeviceInfo() {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400170 Mutex::Autolock autoLock(mMutex);
171
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400172 mRequest.reset();
173 if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO))
174 return NULL;
175 if (!readData())
176 return NULL;
177 MtpResponseCode ret = readResponse();
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400178 if (ret == MTP_RESPONSE_OK) {
179 MtpDeviceInfo* info = new MtpDeviceInfo;
180 info->read(mData);
181 return info;
182 }
183 return NULL;
184}
185
186MtpStorageIDList* MtpDevice::getStorageIDs() {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400187 Mutex::Autolock autoLock(mMutex);
188
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400189 mRequest.reset();
190 if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS))
191 return NULL;
192 if (!readData())
193 return NULL;
194 MtpResponseCode ret = readResponse();
195 if (ret == MTP_RESPONSE_OK) {
196 return mData.getAUInt32();
197 }
198 return NULL;
199}
200
201MtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400202 Mutex::Autolock autoLock(mMutex);
203
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400204 mRequest.reset();
205 mRequest.setParameter(1, storageID);
206 if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO))
207 return NULL;
208 if (!readData())
209 return NULL;
210 MtpResponseCode ret = readResponse();
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400211 if (ret == MTP_RESPONSE_OK) {
212 MtpStorageInfo* info = new MtpStorageInfo(storageID);
213 info->read(mData);
214 return info;
215 }
216 return NULL;
217}
218
219MtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
220 MtpObjectFormat format, MtpObjectHandle parent) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400221 Mutex::Autolock autoLock(mMutex);
222
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400223 mRequest.reset();
224 mRequest.setParameter(1, storageID);
225 mRequest.setParameter(2, format);
226 mRequest.setParameter(3, parent);
227 if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES))
228 return NULL;
229 if (!readData())
230 return NULL;
231 MtpResponseCode ret = readResponse();
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400232 if (ret == MTP_RESPONSE_OK) {
233 return mData.getAUInt32();
234 }
235 return NULL;
236}
237
238MtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400239 Mutex::Autolock autoLock(mMutex);
240
Mike Lockwood6afc41d2010-06-11 16:34:52 -0400241 // FIXME - we might want to add some caching here
242
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400243 mRequest.reset();
244 mRequest.setParameter(1, handle);
245 if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO))
246 return NULL;
247 if (!readData())
248 return NULL;
249 MtpResponseCode ret = readResponse();
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400250 if (ret == MTP_RESPONSE_OK) {
251 MtpObjectInfo* info = new MtpObjectInfo(handle);
252 info->read(mData);
253 return info;
254 }
255 return NULL;
256}
257
Mike Lockwood3e072b32010-06-10 16:34:20 -0400258void* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400259 Mutex::Autolock autoLock(mMutex);
260
Mike Lockwood3e072b32010-06-10 16:34:20 -0400261 mRequest.reset();
262 mRequest.setParameter(1, handle);
263 if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
264 MtpResponseCode ret = readResponse();
265 if (ret == MTP_RESPONSE_OK) {
266 return mData.getData(outLength);
267 }
268 }
269 outLength = 0;
270 return NULL;
Mike Lockwood6afc41d2010-06-11 16:34:52 -0400271}
Mike Lockwood3e072b32010-06-10 16:34:20 -0400272
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400273MtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) {
274 Mutex::Autolock autoLock(mMutex);
275
276 mRequest.reset();
277 MtpObjectHandle parent = info->mParent;
278 if (parent == 0)
279 parent = MTP_PARENT_ROOT;
280
281 mRequest.setParameter(1, info->mStorageID);
282 mRequest.setParameter(2, info->mParent);
283
284 mData.putUInt32(info->mStorageID);
285 mData.putUInt16(info->mFormat);
286 mData.putUInt16(info->mProtectionStatus);
287 mData.putUInt32(info->mCompressedSize);
288 mData.putUInt16(info->mThumbFormat);
289 mData.putUInt32(info->mThumbCompressedSize);
290 mData.putUInt32(info->mThumbPixWidth);
291 mData.putUInt32(info->mThumbPixHeight);
292 mData.putUInt32(info->mImagePixWidth);
293 mData.putUInt32(info->mImagePixHeight);
294 mData.putUInt32(info->mImagePixDepth);
295 mData.putUInt32(info->mParent);
296 mData.putUInt16(info->mAssociationType);
297 mData.putUInt32(info->mAssociationDesc);
298 mData.putUInt32(info->mSequenceNumber);
299 mData.putString(info->mName);
300
301 char created[100], modified[100];
302 formatDateTime(info->mDateCreated, created, sizeof(created));
303 formatDateTime(info->mDateModified, modified, sizeof(modified));
304
305 mData.putString(created);
306 mData.putString(modified);
307 if (info->mKeywords)
308 mData.putString(info->mKeywords);
309 else
310 mData.putEmptyString();
311
312 if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400313 MtpResponseCode ret = readResponse();
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400314 if (ret == MTP_RESPONSE_OK) {
315 info->mStorageID = mResponse.getParameter(1);
316 info->mParent = mResponse.getParameter(2);
317 info->mHandle = mResponse.getParameter(3);
318 return info->mHandle;
319 }
320 }
321 return (MtpObjectHandle)-1;
322}
323
324bool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) {
325 Mutex::Autolock autoLock(mMutex);
326
327 int remaining = info->mCompressedSize;
328 mRequest.reset();
329 mRequest.setParameter(1, info->mHandle);
330 if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400331 // send data header
332 writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
333
334 char buffer[65536];
335 while (remaining > 0) {
336 int count = read(srcFD, buffer, sizeof(buffer));
337 if (count > 0) {
Mike Lockwood42d0b792011-01-04 14:48:57 -0500338 int written = mData.write(mRequestOut, buffer, count);
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400339 // FIXME check error
340 remaining -= count;
341 } else {
342 break;
343 }
344 }
345 }
346 MtpResponseCode ret = readResponse();
347 return (remaining == 0 && ret == MTP_RESPONSE_OK);
348}
349
Mike Lockwood6afc41d2010-06-11 16:34:52 -0400350bool MtpDevice::deleteObject(MtpObjectHandle handle) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400351 Mutex::Autolock autoLock(mMutex);
352
Mike Lockwood6afc41d2010-06-11 16:34:52 -0400353 mRequest.reset();
354 mRequest.setParameter(1, handle);
355 if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) {
356 MtpResponseCode ret = readResponse();
357 if (ret == MTP_RESPONSE_OK)
358 return true;
359 }
360 return false;
361}
362
363MtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) {
364 MtpObjectInfo* info = getObjectInfo(handle);
365 if (info)
366 return info->mParent;
367 else
368 return -1;
369}
370
371MtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) {
372 MtpObjectInfo* info = getObjectInfo(handle);
373 if (info)
374 return info->mStorageID;
375 else
376 return -1;
Mike Lockwood3e072b32010-06-10 16:34:20 -0400377}
378
Mike Lockwood98693f62010-12-07 10:58:56 -0800379MtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) {
380 Mutex::Autolock autoLock(mMutex);
381
382 mRequest.reset();
383 mRequest.setParameter(1, format);
384 if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED))
385 return NULL;
386 if (!readData())
387 return NULL;
388 MtpResponseCode ret = readResponse();
389 if (ret == MTP_RESPONSE_OK) {
390 return mData.getAUInt16();
391 }
392 return NULL;
393
394}
395
Mike Lockwooda6c490b2010-06-05 22:45:01 -0400396MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400397 Mutex::Autolock autoLock(mMutex);
398
Mike Lockwooda6c490b2010-06-05 22:45:01 -0400399 mRequest.reset();
400 mRequest.setParameter(1, code);
401 if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC))
402 return NULL;
403 if (!readData())
404 return NULL;
405 MtpResponseCode ret = readResponse();
406 if (ret == MTP_RESPONSE_OK) {
407 MtpProperty* property = new MtpProperty;
Mike Lockwoode3e76c42010-09-02 14:57:30 -0400408 property->read(mData);
Mike Lockwooda6c490b2010-06-05 22:45:01 -0400409 return property;
410 }
411 return NULL;
412}
413
Mike Lockwood99e393a2010-12-07 18:53:04 -0800414MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) {
Mike Lockwood98693f62010-12-07 10:58:56 -0800415 Mutex::Autolock autoLock(mMutex);
416
417 mRequest.reset();
418 mRequest.setParameter(1, code);
Mike Lockwood99e393a2010-12-07 18:53:04 -0800419 mRequest.setParameter(2, format);
Mike Lockwood98693f62010-12-07 10:58:56 -0800420 if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC))
421 return NULL;
422 if (!readData())
423 return NULL;
424 MtpResponseCode ret = readResponse();
425 if (ret == MTP_RESPONSE_OK) {
426 MtpProperty* property = new MtpProperty;
427 property->read(mData);
428 return property;
429 }
430 return NULL;
431}
432
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500433// reads the object's data and writes it to the specified file path
Mike Lockwood27afe3a2010-11-19 13:52:20 -0500434bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500435 LOGD("readObject: %s", destPath);
436 int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC);
437 if (fd < 0) {
438 LOGE("open failed for %s", destPath);
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400439 return false;
440 }
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400441
Mike Lockwood27afe3a2010-11-19 13:52:20 -0500442 fchown(fd, getuid(), group);
443 // set permissions
444 int mask = umask(0);
445 fchmod(fd, perm);
446 umask(mask);
447
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500448 Mutex::Autolock autoLock(mMutex);
449 bool result = false;
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400450
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500451 mRequest.reset();
452 mRequest.setParameter(1, handle);
453 if (sendRequest(MTP_OPERATION_GET_OBJECT)
Mike Lockwood42d0b792011-01-04 14:48:57 -0500454 && mData.readDataHeader(mRequestIn1)) {
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500455 uint32_t length = mData.getContainerLength();
456 if (length < MTP_CONTAINER_HEADER_SIZE)
457 goto fail;
458 length -= MTP_CONTAINER_HEADER_SIZE;
459 uint32_t remaining = length;
460
461 int initialDataLength = 0;
462 void* initialData = mData.getData(initialDataLength);
463 if (initialData) {
464 if (initialDataLength > 0) {
465 if (write(fd, initialData, initialDataLength) != initialDataLength)
466 goto fail;
467 remaining -= initialDataLength;
468 }
469 free(initialData);
470 }
471
472 // USB reads greater than 16K don't work
473 char buffer1[16384], buffer2[16384];
Mike Lockwood42d0b792011-01-04 14:48:57 -0500474 mRequestIn1->buffer = buffer1;
475 mRequestIn2->buffer = buffer2;
476 struct usb_request* req = mRequestIn1;
477 void* writeBuffer = NULL;
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500478 int writeLength = 0;
479
480 while (remaining > 0 || writeBuffer) {
481 if (remaining > 0) {
482 // queue up a read request
Mike Lockwood42d0b792011-01-04 14:48:57 -0500483 req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
484 if (mData.readDataAsync(req)) {
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500485 LOGE("readDataAsync failed");
486 goto fail;
487 }
488 } else {
Mike Lockwood42d0b792011-01-04 14:48:57 -0500489 req = NULL;
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500490 }
491
492 if (writeBuffer) {
493 // write previous buffer
494 if (write(fd, writeBuffer, writeLength) != writeLength) {
495 LOGE("write failed");
496 // wait for pending read before failing
Mike Lockwood42d0b792011-01-04 14:48:57 -0500497 if (req)
498 mData.readDataWait(mDevice);
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500499 goto fail;
500 }
501 writeBuffer = NULL;
502 }
503
504 // wait for read to complete
Mike Lockwood42d0b792011-01-04 14:48:57 -0500505 if (req) {
506 int read = mData.readDataWait(mDevice);
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500507 if (read < 0)
508 goto fail;
509
Mike Lockwood42d0b792011-01-04 14:48:57 -0500510 writeBuffer = req->buffer;
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500511 writeLength = read;
512 remaining -= read;
Mike Lockwood42d0b792011-01-04 14:48:57 -0500513 req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500514 }
515 }
516
517 MtpResponseCode response = readResponse();
518 if (response == MTP_RESPONSE_OK)
519 result = true;
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400520 }
Mike Lockwoodb9ff4442010-11-19 11:20:19 -0500521
522fail:
523 ::close(fd);
524 return result;
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400525}
Mike Lockwooda6c490b2010-06-05 22:45:01 -0400526
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400527bool MtpDevice::sendRequest(MtpOperationCode operation) {
Mike Lockwoodf43c6412010-07-27 11:50:34 -0400528 LOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
Mike Lockwoodf7454622010-12-09 18:34:18 -0800529 mReceivedResponse = false;
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400530 mRequest.setOperationCode(operation);
531 if (mTransactionID > 0)
532 mRequest.setTransactionID(mTransactionID++);
Mike Lockwood42d0b792011-01-04 14:48:57 -0500533 int ret = mRequest.write(mRequestOut);
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400534 mRequest.dump();
535 return (ret > 0);
536}
537
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400538bool MtpDevice::sendData() {
Mike Lockwoodf43c6412010-07-27 11:50:34 -0400539 LOGV("sendData\n");
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400540 mData.setOperationCode(mRequest.getOperationCode());
541 mData.setTransactionID(mRequest.getTransactionID());
Mike Lockwood42d0b792011-01-04 14:48:57 -0500542 int ret = mData.write(mRequestOut);
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400543 mData.dump();
544 return (ret > 0);
545}
546
547bool MtpDevice::readData() {
548 mData.reset();
Mike Lockwood42d0b792011-01-04 14:48:57 -0500549 int ret = mData.read(mRequestIn1);
Mike Lockwoodf43c6412010-07-27 11:50:34 -0400550 LOGV("readData returned %d\n", ret);
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400551 if (ret >= MTP_CONTAINER_HEADER_SIZE) {
Mike Lockwoodf7454622010-12-09 18:34:18 -0800552 if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
553 LOGD("got response packet instead of data packet");
554 // we got a response packet rather than data
555 // copy it to mResponse
556 mResponse.copyFrom(mData);
557 mReceivedResponse = true;
558 return false;
559 }
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400560 mData.dump();
561 return true;
562 }
563 else {
Mike Lockwoodf43c6412010-07-27 11:50:34 -0400564 LOGV("readResponse failed\n");
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400565 return false;
566 }
567}
568
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400569bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
570 mData.setOperationCode(operation);
571 mData.setTransactionID(mRequest.getTransactionID());
Mike Lockwood42d0b792011-01-04 14:48:57 -0500572 return (!mData.writeDataHeader(mRequestOut, dataLength));
Mike Lockwood0cf89f22010-07-26 20:40:45 -0400573}
574
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400575MtpResponseCode MtpDevice::readResponse() {
Mike Lockwoodf43c6412010-07-27 11:50:34 -0400576 LOGV("readResponse\n");
Mike Lockwoodf7454622010-12-09 18:34:18 -0800577 if (mReceivedResponse) {
578 mReceivedResponse = false;
579 return mResponse.getResponseCode();
580 }
Mike Lockwood42d0b792011-01-04 14:48:57 -0500581 int ret = mResponse.read(mRequestIn1);
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400582 if (ret >= MTP_CONTAINER_HEADER_SIZE) {
583 mResponse.dump();
584 return mResponse.getResponseCode();
Mike Lockwoodf7454622010-12-09 18:34:18 -0800585 } else {
Mike Lockwooda6c490b2010-06-05 22:45:01 -0400586 LOGD("readResponse failed\n");
Mike Lockwood5ed68d22010-05-25 19:08:48 -0400587 return -1;
588 }
589}
590
591} // namespace android