Home | History | Annotate | Download | only in mtp
      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 "MtpDevice"
     18 
     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"
     26 #include "MtpUtils.h"
     27 
     28 #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>
     35 #include <endian.h>
     36 
     37 #include <usbhost/usbhost.h>
     38 
     39 namespace android {
     40 
     41 #if 0
     42 static bool isMtpDevice(uint16_t vendor, uint16_t product) {
     43     // Sandisk Sansa Fuze
     44     if (vendor == 0x0781 && product == 0x74c2)
     45         return true;
     46     // Samsung YP-Z5
     47     if (vendor == 0x04e8 && product == 0x503c)
     48         return true;
     49     return false;
     50 }
     51 #endif
     52 
     53 MtpDevice* MtpDevice::open(const char* deviceName, int fd) {
     54     struct usb_device *device = usb_device_new(deviceName, fd);
     55     if (!device) {
     56         ALOGE("usb_device_new failed for %s", deviceName);
     57         return NULL;
     58     }
     59 
     60     struct usb_descriptor_header* desc;
     61     struct usb_descriptor_iter iter;
     62 
     63     usb_descriptor_iter_init(device, &iter);
     64 
     65     while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {
     66         if (desc->bDescriptorType == USB_DT_INTERFACE) {
     67             struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;
     68 
     69             if (interface->bInterfaceClass == USB_CLASS_STILL_IMAGE &&
     70                 interface->bInterfaceSubClass == 1 && // Still Image Capture
     71                 interface->bInterfaceProtocol == 1)     // Picture Transfer Protocol (PIMA 15470)
     72             {
     73                 char* manufacturerName = usb_device_get_manufacturer_name(device);
     74                 char* productName = usb_device_get_product_name(device);
     75                 ALOGD("Found camera: \"%s\" \"%s\"\n", manufacturerName, productName);
     76                 free(manufacturerName);
     77                 free(productName);
     78             } else if (interface->bInterfaceClass == 0xFF &&
     79                     interface->bInterfaceSubClass == 0xFF &&
     80                     interface->bInterfaceProtocol == 0) {
     81                 char* interfaceName = usb_device_get_string(device, interface->iInterface);
     82                 if (!interfaceName) {
     83                     continue;
     84                 } else if (strcmp(interfaceName, "MTP")) {
     85                     free(interfaceName);
     86                     continue;
     87                 }
     88                 free(interfaceName);
     89 
     90                 // Looks like an android style MTP device
     91                 char* manufacturerName = usb_device_get_manufacturer_name(device);
     92                 char* productName = usb_device_get_product_name(device);
     93                 ALOGD("Found MTP device: \"%s\" \"%s\"\n", manufacturerName, productName);
     94                 free(manufacturerName);
     95                 free(productName);
     96             }
     97 #if 0
     98              else {
     99                 // look for special cased devices based on vendor/product ID
    100                 // we are doing this mainly for testing purposes
    101                 uint16_t vendor = usb_device_get_vendor_id(device);
    102                 uint16_t product = usb_device_get_product_id(device);
    103                 if (!isMtpDevice(vendor, product)) {
    104                     // not an MTP or PTP device
    105                     continue;
    106                 }
    107                 // request MTP OS string and descriptor
    108                 // some music players need to see this before entering MTP mode.
    109                 char buffer[256];
    110                 memset(buffer, 0, sizeof(buffer));
    111                 int ret = usb_device_control_transfer(device,
    112                         USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_STANDARD,
    113                         USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | 0xEE,
    114                         0, buffer, sizeof(buffer), 0);
    115                 printf("usb_device_control_transfer returned %d errno: %d\n", ret, errno);
    116                 if (ret > 0) {
    117                     printf("got MTP string %s\n", buffer);
    118                     ret = usb_device_control_transfer(device,
    119                             USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, 1,
    120                             0, 4, buffer, sizeof(buffer), 0);
    121                     printf("OS descriptor got %d\n", ret);
    122                 } else {
    123                     printf("no MTP string\n");
    124                 }
    125             }
    126 #endif
    127             // if we got here, then we have a likely MTP or PTP device
    128 
    129             // interface should be followed by three endpoints
    130             struct usb_endpoint_descriptor *ep;
    131             struct usb_endpoint_descriptor *ep_in_desc = NULL;
    132             struct usb_endpoint_descriptor *ep_out_desc = NULL;
    133             struct usb_endpoint_descriptor *ep_intr_desc = NULL;
    134             for (int i = 0; i < 3; i++) {
    135                 ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
    136                 if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) {
    137                     ALOGE("endpoints not found\n");
    138                     usb_device_close(device);
    139                     return NULL;
    140                 }
    141                 if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
    142                     if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
    143                         ep_in_desc = ep;
    144                     else
    145                         ep_out_desc = ep;
    146                 } else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT &&
    147                     ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
    148                     ep_intr_desc = ep;
    149                 }
    150             }
    151             if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) {
    152                 ALOGE("endpoints not found\n");
    153                 usb_device_close(device);
    154                 return NULL;
    155             }
    156 
    157             if (usb_device_claim_interface(device, interface->bInterfaceNumber)) {
    158                 ALOGE("usb_device_claim_interface failed errno: %d\n", errno);
    159                 usb_device_close(device);
    160                 return NULL;
    161             }
    162 
    163             MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber,
    164                         ep_in_desc, ep_out_desc, ep_intr_desc);
    165             mtpDevice->initialize();
    166             return mtpDevice;
    167         }
    168     }
    169 
    170     usb_device_close(device);
    171     ALOGE("device not found");
    172     return NULL;
    173 }
    174 
    175 MtpDevice::MtpDevice(struct usb_device* device, int interface,
    176             const struct usb_endpoint_descriptor *ep_in,
    177             const struct usb_endpoint_descriptor *ep_out,
    178             const struct usb_endpoint_descriptor *ep_intr)
    179     :   mDevice(device),
    180         mInterface(interface),
    181         mRequestIn1(NULL),
    182         mRequestIn2(NULL),
    183         mRequestOut(NULL),
    184         mRequestIntr(NULL),
    185         mDeviceInfo(NULL),
    186         mSessionID(0),
    187         mTransactionID(0),
    188         mReceivedResponse(false)
    189 {
    190     mRequestIn1 = usb_request_new(device, ep_in);
    191     mRequestIn2 = usb_request_new(device, ep_in);
    192     mRequestOut = usb_request_new(device, ep_out);
    193     mRequestIntr = usb_request_new(device, ep_intr);
    194 }
    195 
    196 MtpDevice::~MtpDevice() {
    197     close();
    198     for (int i = 0; i < mDeviceProperties.size(); i++)
    199         delete mDeviceProperties[i];
    200     usb_request_free(mRequestIn1);
    201     usb_request_free(mRequestIn2);
    202     usb_request_free(mRequestOut);
    203     usb_request_free(mRequestIntr);
    204 }
    205 
    206 void MtpDevice::initialize() {
    207     openSession();
    208     mDeviceInfo = getDeviceInfo();
    209     if (mDeviceInfo) {
    210         if (mDeviceInfo->mDeviceProperties) {
    211             int count = mDeviceInfo->mDeviceProperties->size();
    212             for (int i = 0; i < count; i++) {
    213                 MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
    214                 MtpProperty* property = getDevicePropDesc(propCode);
    215                 if (property)
    216                     mDeviceProperties.push(property);
    217             }
    218         }
    219     }
    220 }
    221 
    222 void MtpDevice::close() {
    223     if (mDevice) {
    224         usb_device_release_interface(mDevice, mInterface);
    225         usb_device_close(mDevice);
    226         mDevice = NULL;
    227     }
    228 }
    229 
    230 void MtpDevice::print() {
    231     if (mDeviceInfo) {
    232         mDeviceInfo->print();
    233 
    234         if (mDeviceInfo->mDeviceProperties) {
    235             ALOGI("***** DEVICE PROPERTIES *****\n");
    236             int count = mDeviceInfo->mDeviceProperties->size();
    237             for (int i = 0; i < count; i++) {
    238                 MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
    239                 MtpProperty* property = getDevicePropDesc(propCode);
    240                 if (property) {
    241                     property->print();
    242                     delete property;
    243                 }
    244             }
    245         }
    246     }
    247 
    248     if (mDeviceInfo->mPlaybackFormats) {
    249             ALOGI("***** OBJECT PROPERTIES *****\n");
    250         int count = mDeviceInfo->mPlaybackFormats->size();
    251         for (int i = 0; i < count; i++) {
    252             MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i];
    253             ALOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format));
    254             MtpObjectPropertyList* props = getObjectPropsSupported(format);
    255             if (props) {
    256                 for (int j = 0; j < props->size(); j++) {
    257                     MtpObjectProperty prop = (*props)[j];
    258                     MtpProperty* property = getObjectPropDesc(prop, format);
    259                     if (property) {
    260                         property->print();
    261                         delete property;
    262                     } else {
    263                         ALOGE("could not fetch property: %s",
    264                                 MtpDebug::getObjectPropCodeName(prop));
    265                     }
    266                 }
    267             }
    268         }
    269     }
    270 }
    271 
    272 const char* MtpDevice::getDeviceName() {
    273     if (mDevice)
    274         return usb_device_get_name(mDevice);
    275     else
    276         return "???";
    277 }
    278 
    279 bool MtpDevice::openSession() {
    280     Mutex::Autolock autoLock(mMutex);
    281 
    282     mSessionID = 0;
    283     mTransactionID = 0;
    284     MtpSessionID newSession = 1;
    285     mRequest.reset();
    286     mRequest.setParameter(1, newSession);
    287     if (!sendRequest(MTP_OPERATION_OPEN_SESSION))
    288         return false;
    289     MtpResponseCode ret = readResponse();
    290     if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN)
    291         newSession = mResponse.getParameter(1);
    292     else if (ret != MTP_RESPONSE_OK)
    293         return false;
    294 
    295     mSessionID = newSession;
    296     mTransactionID = 1;
    297     return true;
    298 }
    299 
    300 bool MtpDevice::closeSession() {
    301     // FIXME
    302     return true;
    303 }
    304 
    305 MtpDeviceInfo* MtpDevice::getDeviceInfo() {
    306     Mutex::Autolock autoLock(mMutex);
    307 
    308     mRequest.reset();
    309     if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO))
    310         return NULL;
    311     if (!readData())
    312         return NULL;
    313     MtpResponseCode ret = readResponse();
    314     if (ret == MTP_RESPONSE_OK) {
    315         MtpDeviceInfo* info = new MtpDeviceInfo;
    316         info->read(mData);
    317         return info;
    318     }
    319     return NULL;
    320 }
    321 
    322 MtpStorageIDList* MtpDevice::getStorageIDs() {
    323     Mutex::Autolock autoLock(mMutex);
    324 
    325     mRequest.reset();
    326     if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS))
    327         return NULL;
    328     if (!readData())
    329         return NULL;
    330     MtpResponseCode ret = readResponse();
    331     if (ret == MTP_RESPONSE_OK) {
    332         return mData.getAUInt32();
    333     }
    334     return NULL;
    335 }
    336 
    337 MtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
    338     Mutex::Autolock autoLock(mMutex);
    339 
    340     mRequest.reset();
    341     mRequest.setParameter(1, storageID);
    342     if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO))
    343         return NULL;
    344     if (!readData())
    345         return NULL;
    346     MtpResponseCode ret = readResponse();
    347     if (ret == MTP_RESPONSE_OK) {
    348         MtpStorageInfo* info = new MtpStorageInfo(storageID);
    349         info->read(mData);
    350         return info;
    351     }
    352     return NULL;
    353 }
    354 
    355 MtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
    356             MtpObjectFormat format, MtpObjectHandle parent) {
    357     Mutex::Autolock autoLock(mMutex);
    358 
    359     mRequest.reset();
    360     mRequest.setParameter(1, storageID);
    361     mRequest.setParameter(2, format);
    362     mRequest.setParameter(3, parent);
    363     if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES))
    364         return NULL;
    365     if (!readData())
    366         return NULL;
    367     MtpResponseCode ret = readResponse();
    368     if (ret == MTP_RESPONSE_OK) {
    369         return mData.getAUInt32();
    370     }
    371     return NULL;
    372 }
    373 
    374 MtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
    375     Mutex::Autolock autoLock(mMutex);
    376 
    377     // FIXME - we might want to add some caching here
    378 
    379     mRequest.reset();
    380     mRequest.setParameter(1, handle);
    381     if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO))
    382         return NULL;
    383     if (!readData())
    384         return NULL;
    385     MtpResponseCode ret = readResponse();
    386     if (ret == MTP_RESPONSE_OK) {
    387         MtpObjectInfo* info = new MtpObjectInfo(handle);
    388         info->read(mData);
    389         return info;
    390     }
    391     return NULL;
    392 }
    393 
    394 void* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) {
    395     Mutex::Autolock autoLock(mMutex);
    396 
    397     mRequest.reset();
    398     mRequest.setParameter(1, handle);
    399     if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
    400         MtpResponseCode ret = readResponse();
    401         if (ret == MTP_RESPONSE_OK) {
    402             return mData.getData(outLength);
    403         }
    404     }
    405     outLength = 0;
    406     return NULL;
    407 }
    408 
    409 MtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) {
    410     Mutex::Autolock autoLock(mMutex);
    411 
    412     mRequest.reset();
    413     MtpObjectHandle parent = info->mParent;
    414     if (parent == 0)
    415         parent = MTP_PARENT_ROOT;
    416 
    417     mRequest.setParameter(1, info->mStorageID);
    418     mRequest.setParameter(2, info->mParent);
    419 
    420     mData.putUInt32(info->mStorageID);
    421     mData.putUInt16(info->mFormat);
    422     mData.putUInt16(info->mProtectionStatus);
    423     mData.putUInt32(info->mCompressedSize);
    424     mData.putUInt16(info->mThumbFormat);
    425     mData.putUInt32(info->mThumbCompressedSize);
    426     mData.putUInt32(info->mThumbPixWidth);
    427     mData.putUInt32(info->mThumbPixHeight);
    428     mData.putUInt32(info->mImagePixWidth);
    429     mData.putUInt32(info->mImagePixHeight);
    430     mData.putUInt32(info->mImagePixDepth);
    431     mData.putUInt32(info->mParent);
    432     mData.putUInt16(info->mAssociationType);
    433     mData.putUInt32(info->mAssociationDesc);
    434     mData.putUInt32(info->mSequenceNumber);
    435     mData.putString(info->mName);
    436 
    437     char created[100], modified[100];
    438     formatDateTime(info->mDateCreated, created, sizeof(created));
    439     formatDateTime(info->mDateModified, modified, sizeof(modified));
    440 
    441     mData.putString(created);
    442     mData.putString(modified);
    443     if (info->mKeywords)
    444         mData.putString(info->mKeywords);
    445     else
    446         mData.putEmptyString();
    447 
    448    if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
    449         MtpResponseCode ret = readResponse();
    450         if (ret == MTP_RESPONSE_OK) {
    451             info->mStorageID = mResponse.getParameter(1);
    452             info->mParent = mResponse.getParameter(2);
    453             info->mHandle = mResponse.getParameter(3);
    454             return info->mHandle;
    455         }
    456     }
    457     return (MtpObjectHandle)-1;
    458 }
    459 
    460 bool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) {
    461     Mutex::Autolock autoLock(mMutex);
    462 
    463     int remaining = info->mCompressedSize;
    464     mRequest.reset();
    465     mRequest.setParameter(1, info->mHandle);
    466     if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
    467         // send data header
    468         writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
    469 
    470         char buffer[65536];
    471         while (remaining > 0) {
    472             int count = read(srcFD, buffer, sizeof(buffer));
    473             if (count > 0) {
    474                 int written = mData.write(mRequestOut, buffer, count);
    475                 // FIXME check error
    476                 remaining -= count;
    477             } else {
    478                 break;
    479             }
    480         }
    481     }
    482     MtpResponseCode ret = readResponse();
    483     return (remaining == 0 && ret == MTP_RESPONSE_OK);
    484 }
    485 
    486 bool MtpDevice::deleteObject(MtpObjectHandle handle) {
    487     Mutex::Autolock autoLock(mMutex);
    488 
    489     mRequest.reset();
    490     mRequest.setParameter(1, handle);
    491     if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) {
    492         MtpResponseCode ret = readResponse();
    493         if (ret == MTP_RESPONSE_OK)
    494             return true;
    495     }
    496     return false;
    497 }
    498 
    499 MtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) {
    500     MtpObjectInfo* info = getObjectInfo(handle);
    501     if (info) {
    502         MtpObjectHandle parent = info->mParent;
    503         delete info;
    504         return parent;
    505     } else {
    506         return -1;
    507     }
    508 }
    509 
    510 MtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) {
    511     MtpObjectInfo* info = getObjectInfo(handle);
    512     if (info) {
    513         MtpObjectHandle storageId = info->mStorageID;
    514         delete info;
    515         return storageId;
    516     } else {
    517         return -1;
    518     }
    519 }
    520 
    521 MtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) {
    522     Mutex::Autolock autoLock(mMutex);
    523 
    524     mRequest.reset();
    525     mRequest.setParameter(1, format);
    526     if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED))
    527         return NULL;
    528     if (!readData())
    529         return NULL;
    530     MtpResponseCode ret = readResponse();
    531     if (ret == MTP_RESPONSE_OK) {
    532         return mData.getAUInt16();
    533     }
    534     return NULL;
    535 
    536 }
    537 
    538 MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
    539     Mutex::Autolock autoLock(mMutex);
    540 
    541     mRequest.reset();
    542     mRequest.setParameter(1, code);
    543     if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC))
    544         return NULL;
    545     if (!readData())
    546         return NULL;
    547     MtpResponseCode ret = readResponse();
    548     if (ret == MTP_RESPONSE_OK) {
    549         MtpProperty* property = new MtpProperty;
    550         property->read(mData);
    551         return property;
    552     }
    553     return NULL;
    554 }
    555 
    556 MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) {
    557     Mutex::Autolock autoLock(mMutex);
    558 
    559     mRequest.reset();
    560     mRequest.setParameter(1, code);
    561     mRequest.setParameter(2, format);
    562     if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC))
    563         return NULL;
    564     if (!readData())
    565         return NULL;
    566     MtpResponseCode ret = readResponse();
    567     if (ret == MTP_RESPONSE_OK) {
    568         MtpProperty* property = new MtpProperty;
    569         property->read(mData);
    570         return property;
    571     }
    572     return NULL;
    573 }
    574 
    575 bool MtpDevice::readObject(MtpObjectHandle handle,
    576         bool (* callback)(void* data, int offset, int length, void* clientData),
    577         int objectSize, void* clientData) {
    578     Mutex::Autolock autoLock(mMutex);
    579     bool result = false;
    580 
    581     mRequest.reset();
    582     mRequest.setParameter(1, handle);
    583     if (sendRequest(MTP_OPERATION_GET_OBJECT)
    584             && mData.readDataHeader(mRequestIn1)) {
    585         uint32_t length = mData.getContainerLength();
    586         if (length - MTP_CONTAINER_HEADER_SIZE != objectSize) {
    587             ALOGE("readObject error objectSize: %d, length: %d",
    588                     objectSize, length);
    589             goto fail;
    590         }
    591         length -= MTP_CONTAINER_HEADER_SIZE;
    592         uint32_t remaining = length;
    593         int offset = 0;
    594 
    595         int initialDataLength = 0;
    596         void* initialData = mData.getData(initialDataLength);
    597         if (initialData) {
    598             if (initialDataLength > 0) {
    599                 if (!callback(initialData, 0, initialDataLength, clientData))
    600                     goto fail;
    601                 remaining -= initialDataLength;
    602                 offset += initialDataLength;
    603             }
    604             free(initialData);
    605         }
    606 
    607         // USB reads greater than 16K don't work
    608         char buffer1[16384], buffer2[16384];
    609         mRequestIn1->buffer = buffer1;
    610         mRequestIn2->buffer = buffer2;
    611         struct usb_request* req = mRequestIn1;
    612         void* writeBuffer = NULL;
    613         int writeLength = 0;
    614 
    615         while (remaining > 0 || writeBuffer) {
    616             if (remaining > 0) {
    617                 // queue up a read request
    618                 req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
    619                 if (mData.readDataAsync(req)) {
    620                     ALOGE("readDataAsync failed");
    621                     goto fail;
    622                 }
    623             } else {
    624                 req = NULL;
    625             }
    626 
    627             if (writeBuffer) {
    628                 // write previous buffer
    629                 if (!callback(writeBuffer, offset, writeLength, clientData)) {
    630                     ALOGE("write failed");
    631                     // wait for pending read before failing
    632                     if (req)
    633                         mData.readDataWait(mDevice);
    634                     goto fail;
    635                 }
    636                 offset += writeLength;
    637                 writeBuffer = NULL;
    638             }
    639 
    640             // wait for read to complete
    641             if (req) {
    642                 int read = mData.readDataWait(mDevice);
    643                 if (read < 0)
    644                     goto fail;
    645 
    646                 if (read > 0) {
    647                     writeBuffer = req->buffer;
    648                     writeLength = read;
    649                     remaining -= read;
    650                     req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
    651                 } else {
    652                     writeBuffer = NULL;
    653                 }
    654             }
    655         }
    656 
    657         MtpResponseCode response = readResponse();
    658         if (response == MTP_RESPONSE_OK)
    659             result = true;
    660     }
    661 
    662 fail:
    663     return result;
    664 }
    665 
    666 
    667 // reads the object's data and writes it to the specified file path
    668 bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
    669     ALOGD("readObject: %s", destPath);
    670     int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    671     if (fd < 0) {
    672         ALOGE("open failed for %s", destPath);
    673         return false;
    674     }
    675 
    676     fchown(fd, getuid(), group);
    677     // set permissions
    678     int mask = umask(0);
    679     fchmod(fd, perm);
    680     umask(mask);
    681 
    682     Mutex::Autolock autoLock(mMutex);
    683     bool result = false;
    684 
    685     mRequest.reset();
    686     mRequest.setParameter(1, handle);
    687     if (sendRequest(MTP_OPERATION_GET_OBJECT)
    688             && mData.readDataHeader(mRequestIn1)) {
    689         uint32_t length = mData.getContainerLength();
    690         if (length < MTP_CONTAINER_HEADER_SIZE)
    691             goto fail;
    692         length -= MTP_CONTAINER_HEADER_SIZE;
    693         uint32_t remaining = length;
    694 
    695         int initialDataLength = 0;
    696         void* initialData = mData.getData(initialDataLength);
    697         if (initialData) {
    698             if (initialDataLength > 0) {
    699                 if (write(fd, initialData, initialDataLength) != initialDataLength) {
    700                     free(initialData);
    701                     goto fail;
    702                 }
    703                 remaining -= initialDataLength;
    704             }
    705             free(initialData);
    706         }
    707 
    708         // USB reads greater than 16K don't work
    709         char buffer1[16384], buffer2[16384];
    710         mRequestIn1->buffer = buffer1;
    711         mRequestIn2->buffer = buffer2;
    712         struct usb_request* req = mRequestIn1;
    713         void* writeBuffer = NULL;
    714         int writeLength = 0;
    715 
    716         while (remaining > 0 || writeBuffer) {
    717             if (remaining > 0) {
    718                 // queue up a read request
    719                 req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
    720                 if (mData.readDataAsync(req)) {
    721                     ALOGE("readDataAsync failed");
    722                     goto fail;
    723                 }
    724             } else {
    725                 req = NULL;
    726             }
    727 
    728             if (writeBuffer) {
    729                 // write previous buffer
    730                 if (write(fd, writeBuffer, writeLength) != writeLength) {
    731                     ALOGE("write failed");
    732                     // wait for pending read before failing
    733                     if (req)
    734                         mData.readDataWait(mDevice);
    735                     goto fail;
    736                 }
    737                 writeBuffer = NULL;
    738             }
    739 
    740             // wait for read to complete
    741             if (req) {
    742                 int read = mData.readDataWait(mDevice);
    743                 if (read < 0)
    744                     goto fail;
    745 
    746                 if (read > 0) {
    747                     writeBuffer = req->buffer;
    748                     writeLength = read;
    749                     remaining -= read;
    750                     req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
    751                 } else {
    752                     writeBuffer = NULL;
    753                 }
    754             }
    755         }
    756 
    757         MtpResponseCode response = readResponse();
    758         if (response == MTP_RESPONSE_OK)
    759             result = true;
    760     }
    761 
    762 fail:
    763     ::close(fd);
    764     return result;
    765 }
    766 
    767 bool MtpDevice::sendRequest(MtpOperationCode operation) {
    768     ALOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
    769     mReceivedResponse = false;
    770     mRequest.setOperationCode(operation);
    771     if (mTransactionID > 0)
    772         mRequest.setTransactionID(mTransactionID++);
    773     int ret = mRequest.write(mRequestOut);
    774     mRequest.dump();
    775     return (ret > 0);
    776 }
    777 
    778 bool MtpDevice::sendData() {
    779     ALOGV("sendData\n");
    780     mData.setOperationCode(mRequest.getOperationCode());
    781     mData.setTransactionID(mRequest.getTransactionID());
    782     int ret = mData.write(mRequestOut);
    783     mData.dump();
    784     return (ret > 0);
    785 }
    786 
    787 bool MtpDevice::readData() {
    788     mData.reset();
    789     int ret = mData.read(mRequestIn1);
    790     ALOGV("readData returned %d\n", ret);
    791     if (ret >= MTP_CONTAINER_HEADER_SIZE) {
    792         if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
    793             ALOGD("got response packet instead of data packet");
    794             // we got a response packet rather than data
    795             // copy it to mResponse
    796             mResponse.copyFrom(mData);
    797             mReceivedResponse = true;
    798             return false;
    799         }
    800         mData.dump();
    801         return true;
    802     }
    803     else {
    804         ALOGV("readResponse failed\n");
    805         return false;
    806     }
    807 }
    808 
    809 bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
    810     mData.setOperationCode(operation);
    811     mData.setTransactionID(mRequest.getTransactionID());
    812     return (!mData.writeDataHeader(mRequestOut, dataLength));
    813 }
    814 
    815 MtpResponseCode MtpDevice::readResponse() {
    816     ALOGV("readResponse\n");
    817     if (mReceivedResponse) {
    818         mReceivedResponse = false;
    819         return mResponse.getResponseCode();
    820     }
    821     int ret = mResponse.read(mRequestIn1);
    822     // handle zero length packets, which might occur if the data transfer
    823     // ends on a packet boundary
    824     if (ret == 0)
    825         ret = mResponse.read(mRequestIn1);
    826     if (ret >= MTP_CONTAINER_HEADER_SIZE) {
    827         mResponse.dump();
    828         return mResponse.getResponseCode();
    829     } else {
    830         ALOGD("readResponse failed\n");
    831         return -1;
    832     }
    833 }
    834 
    835 }  // namespace android
    836