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 (size_t 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 (size_t 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         if (info->read(mData))
    317             return info;
    318         else
    319             delete info;
    320     }
    321     return NULL;
    322 }
    323 
    324 MtpStorageIDList* MtpDevice::getStorageIDs() {
    325     Mutex::Autolock autoLock(mMutex);
    326 
    327     mRequest.reset();
    328     if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS))
    329         return NULL;
    330     if (!readData())
    331         return NULL;
    332     MtpResponseCode ret = readResponse();
    333     if (ret == MTP_RESPONSE_OK) {
    334         return mData.getAUInt32();
    335     }
    336     return NULL;
    337 }
    338 
    339 MtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
    340     Mutex::Autolock autoLock(mMutex);
    341 
    342     mRequest.reset();
    343     mRequest.setParameter(1, storageID);
    344     if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO))
    345         return NULL;
    346     if (!readData())
    347         return NULL;
    348     MtpResponseCode ret = readResponse();
    349     if (ret == MTP_RESPONSE_OK) {
    350         MtpStorageInfo* info = new MtpStorageInfo(storageID);
    351         if (info->read(mData))
    352             return info;
    353         else
    354             delete info;
    355     }
    356     return NULL;
    357 }
    358 
    359 MtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
    360             MtpObjectFormat format, MtpObjectHandle parent) {
    361     Mutex::Autolock autoLock(mMutex);
    362 
    363     mRequest.reset();
    364     mRequest.setParameter(1, storageID);
    365     mRequest.setParameter(2, format);
    366     mRequest.setParameter(3, parent);
    367     if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES))
    368         return NULL;
    369     if (!readData())
    370         return NULL;
    371     MtpResponseCode ret = readResponse();
    372     if (ret == MTP_RESPONSE_OK) {
    373         return mData.getAUInt32();
    374     }
    375     return NULL;
    376 }
    377 
    378 MtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
    379     Mutex::Autolock autoLock(mMutex);
    380 
    381     // FIXME - we might want to add some caching here
    382 
    383     mRequest.reset();
    384     mRequest.setParameter(1, handle);
    385     if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO))
    386         return NULL;
    387     if (!readData())
    388         return NULL;
    389     MtpResponseCode ret = readResponse();
    390     if (ret == MTP_RESPONSE_OK) {
    391         MtpObjectInfo* info = new MtpObjectInfo(handle);
    392         if (info->read(mData))
    393             return info;
    394         else
    395             delete info;
    396     }
    397     return NULL;
    398 }
    399 
    400 void* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) {
    401     Mutex::Autolock autoLock(mMutex);
    402 
    403     mRequest.reset();
    404     mRequest.setParameter(1, handle);
    405     if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
    406         MtpResponseCode ret = readResponse();
    407         if (ret == MTP_RESPONSE_OK) {
    408             return mData.getData(outLength);
    409         }
    410     }
    411     outLength = 0;
    412     return NULL;
    413 }
    414 
    415 MtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) {
    416     Mutex::Autolock autoLock(mMutex);
    417 
    418     mRequest.reset();
    419     MtpObjectHandle parent = info->mParent;
    420     if (parent == 0)
    421         parent = MTP_PARENT_ROOT;
    422 
    423     mRequest.setParameter(1, info->mStorageID);
    424     mRequest.setParameter(2, info->mParent);
    425 
    426     mData.putUInt32(info->mStorageID);
    427     mData.putUInt16(info->mFormat);
    428     mData.putUInt16(info->mProtectionStatus);
    429     mData.putUInt32(info->mCompressedSize);
    430     mData.putUInt16(info->mThumbFormat);
    431     mData.putUInt32(info->mThumbCompressedSize);
    432     mData.putUInt32(info->mThumbPixWidth);
    433     mData.putUInt32(info->mThumbPixHeight);
    434     mData.putUInt32(info->mImagePixWidth);
    435     mData.putUInt32(info->mImagePixHeight);
    436     mData.putUInt32(info->mImagePixDepth);
    437     mData.putUInt32(info->mParent);
    438     mData.putUInt16(info->mAssociationType);
    439     mData.putUInt32(info->mAssociationDesc);
    440     mData.putUInt32(info->mSequenceNumber);
    441     mData.putString(info->mName);
    442 
    443     char created[100], modified[100];
    444     formatDateTime(info->mDateCreated, created, sizeof(created));
    445     formatDateTime(info->mDateModified, modified, sizeof(modified));
    446 
    447     mData.putString(created);
    448     mData.putString(modified);
    449     if (info->mKeywords)
    450         mData.putString(info->mKeywords);
    451     else
    452         mData.putEmptyString();
    453 
    454    if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
    455         MtpResponseCode ret = readResponse();
    456         if (ret == MTP_RESPONSE_OK) {
    457             info->mStorageID = mResponse.getParameter(1);
    458             info->mParent = mResponse.getParameter(2);
    459             info->mHandle = mResponse.getParameter(3);
    460             return info->mHandle;
    461         }
    462     }
    463     return (MtpObjectHandle)-1;
    464 }
    465 
    466 bool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) {
    467     Mutex::Autolock autoLock(mMutex);
    468 
    469     int remaining = info->mCompressedSize;
    470     mRequest.reset();
    471     mRequest.setParameter(1, info->mHandle);
    472     if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
    473         // send data header
    474         writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
    475 
    476         char buffer[65536];
    477         while (remaining > 0) {
    478             int count = read(srcFD, buffer, sizeof(buffer));
    479             if (count > 0) {
    480                 int written = mData.write(mRequestOut, buffer, count);
    481                 // FIXME check error
    482                 remaining -= count;
    483             } else {
    484                 break;
    485             }
    486         }
    487     }
    488     MtpResponseCode ret = readResponse();
    489     return (remaining == 0 && ret == MTP_RESPONSE_OK);
    490 }
    491 
    492 bool MtpDevice::deleteObject(MtpObjectHandle handle) {
    493     Mutex::Autolock autoLock(mMutex);
    494 
    495     mRequest.reset();
    496     mRequest.setParameter(1, handle);
    497     if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) {
    498         MtpResponseCode ret = readResponse();
    499         if (ret == MTP_RESPONSE_OK)
    500             return true;
    501     }
    502     return false;
    503 }
    504 
    505 MtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) {
    506     MtpObjectInfo* info = getObjectInfo(handle);
    507     if (info) {
    508         MtpObjectHandle parent = info->mParent;
    509         delete info;
    510         return parent;
    511     } else {
    512         return -1;
    513     }
    514 }
    515 
    516 MtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) {
    517     MtpObjectInfo* info = getObjectInfo(handle);
    518     if (info) {
    519         MtpObjectHandle storageId = info->mStorageID;
    520         delete info;
    521         return storageId;
    522     } else {
    523         return -1;
    524     }
    525 }
    526 
    527 MtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) {
    528     Mutex::Autolock autoLock(mMutex);
    529 
    530     mRequest.reset();
    531     mRequest.setParameter(1, format);
    532     if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED))
    533         return NULL;
    534     if (!readData())
    535         return NULL;
    536     MtpResponseCode ret = readResponse();
    537     if (ret == MTP_RESPONSE_OK) {
    538         return mData.getAUInt16();
    539     }
    540     return NULL;
    541 
    542 }
    543 
    544 MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
    545     Mutex::Autolock autoLock(mMutex);
    546 
    547     mRequest.reset();
    548     mRequest.setParameter(1, code);
    549     if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC))
    550         return NULL;
    551     if (!readData())
    552         return NULL;
    553     MtpResponseCode ret = readResponse();
    554     if (ret == MTP_RESPONSE_OK) {
    555         MtpProperty* property = new MtpProperty;
    556         if (property->read(mData))
    557             return property;
    558         else
    559             delete property;
    560     }
    561     return NULL;
    562 }
    563 
    564 MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) {
    565     Mutex::Autolock autoLock(mMutex);
    566 
    567     mRequest.reset();
    568     mRequest.setParameter(1, code);
    569     mRequest.setParameter(2, format);
    570     if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC))
    571         return NULL;
    572     if (!readData())
    573         return NULL;
    574     MtpResponseCode ret = readResponse();
    575     if (ret == MTP_RESPONSE_OK) {
    576         MtpProperty* property = new MtpProperty;
    577         if (property->read(mData))
    578             return property;
    579         else
    580             delete property;
    581     }
    582     return NULL;
    583 }
    584 
    585 bool MtpDevice::readObject(MtpObjectHandle handle,
    586         bool (* callback)(void* data, int offset, int length, void* clientData),
    587         size_t objectSize, void* clientData) {
    588     Mutex::Autolock autoLock(mMutex);
    589     bool result = false;
    590 
    591     mRequest.reset();
    592     mRequest.setParameter(1, handle);
    593     if (sendRequest(MTP_OPERATION_GET_OBJECT)
    594             && mData.readDataHeader(mRequestIn1)) {
    595         uint32_t length = mData.getContainerLength();
    596         if (length - MTP_CONTAINER_HEADER_SIZE != objectSize) {
    597             ALOGE("readObject error objectSize: %d, length: %d",
    598                     objectSize, length);
    599             goto fail;
    600         }
    601         length -= MTP_CONTAINER_HEADER_SIZE;
    602         uint32_t remaining = length;
    603         int offset = 0;
    604 
    605         int initialDataLength = 0;
    606         void* initialData = mData.getData(initialDataLength);
    607         if (initialData) {
    608             if (initialDataLength > 0) {
    609                 if (!callback(initialData, 0, initialDataLength, clientData))
    610                     goto fail;
    611                 remaining -= initialDataLength;
    612                 offset += initialDataLength;
    613             }
    614             free(initialData);
    615         }
    616 
    617         // USB reads greater than 16K don't work
    618         char buffer1[16384], buffer2[16384];
    619         mRequestIn1->buffer = buffer1;
    620         mRequestIn2->buffer = buffer2;
    621         struct usb_request* req = mRequestIn1;
    622         void* writeBuffer = NULL;
    623         int writeLength = 0;
    624 
    625         while (remaining > 0 || writeBuffer) {
    626             if (remaining > 0) {
    627                 // queue up a read request
    628                 req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
    629                 if (mData.readDataAsync(req)) {
    630                     ALOGE("readDataAsync failed");
    631                     goto fail;
    632                 }
    633             } else {
    634                 req = NULL;
    635             }
    636 
    637             if (writeBuffer) {
    638                 // write previous buffer
    639                 if (!callback(writeBuffer, offset, writeLength, clientData)) {
    640                     ALOGE("write failed");
    641                     // wait for pending read before failing
    642                     if (req)
    643                         mData.readDataWait(mDevice);
    644                     goto fail;
    645                 }
    646                 offset += writeLength;
    647                 writeBuffer = NULL;
    648             }
    649 
    650             // wait for read to complete
    651             if (req) {
    652                 int read = mData.readDataWait(mDevice);
    653                 if (read < 0)
    654                     goto fail;
    655 
    656                 if (read > 0) {
    657                     writeBuffer = req->buffer;
    658                     writeLength = read;
    659                     remaining -= read;
    660                     req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
    661                 } else {
    662                     writeBuffer = NULL;
    663                 }
    664             }
    665         }
    666 
    667         MtpResponseCode response = readResponse();
    668         if (response == MTP_RESPONSE_OK)
    669             result = true;
    670     }
    671 
    672 fail:
    673     return result;
    674 }
    675 
    676 
    677 // reads the object's data and writes it to the specified file path
    678 bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
    679     ALOGD("readObject: %s", destPath);
    680     int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    681     if (fd < 0) {
    682         ALOGE("open failed for %s", destPath);
    683         return false;
    684     }
    685 
    686     fchown(fd, getuid(), group);
    687     // set permissions
    688     int mask = umask(0);
    689     fchmod(fd, perm);
    690     umask(mask);
    691 
    692     Mutex::Autolock autoLock(mMutex);
    693     bool result = false;
    694 
    695     mRequest.reset();
    696     mRequest.setParameter(1, handle);
    697     if (sendRequest(MTP_OPERATION_GET_OBJECT)
    698             && mData.readDataHeader(mRequestIn1)) {
    699         uint32_t length = mData.getContainerLength();
    700         if (length < MTP_CONTAINER_HEADER_SIZE)
    701             goto fail;
    702         length -= MTP_CONTAINER_HEADER_SIZE;
    703         uint32_t remaining = length;
    704 
    705         int initialDataLength = 0;
    706         void* initialData = mData.getData(initialDataLength);
    707         if (initialData) {
    708             if (initialDataLength > 0) {
    709                 if (write(fd, initialData, initialDataLength) != initialDataLength) {
    710                     free(initialData);
    711                     goto fail;
    712                 }
    713                 remaining -= initialDataLength;
    714             }
    715             free(initialData);
    716         }
    717 
    718         // USB reads greater than 16K don't work
    719         char buffer1[16384], buffer2[16384];
    720         mRequestIn1->buffer = buffer1;
    721         mRequestIn2->buffer = buffer2;
    722         struct usb_request* req = mRequestIn1;
    723         void* writeBuffer = NULL;
    724         int writeLength = 0;
    725 
    726         while (remaining > 0 || writeBuffer) {
    727             if (remaining > 0) {
    728                 // queue up a read request
    729                 req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
    730                 if (mData.readDataAsync(req)) {
    731                     ALOGE("readDataAsync failed");
    732                     goto fail;
    733                 }
    734             } else {
    735                 req = NULL;
    736             }
    737 
    738             if (writeBuffer) {
    739                 // write previous buffer
    740                 if (write(fd, writeBuffer, writeLength) != writeLength) {
    741                     ALOGE("write failed");
    742                     // wait for pending read before failing
    743                     if (req)
    744                         mData.readDataWait(mDevice);
    745                     goto fail;
    746                 }
    747                 writeBuffer = NULL;
    748             }
    749 
    750             // wait for read to complete
    751             if (req) {
    752                 int read = mData.readDataWait(mDevice);
    753                 if (read < 0)
    754                     goto fail;
    755 
    756                 if (read > 0) {
    757                     writeBuffer = req->buffer;
    758                     writeLength = read;
    759                     remaining -= read;
    760                     req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
    761                 } else {
    762                     writeBuffer = NULL;
    763                 }
    764             }
    765         }
    766 
    767         MtpResponseCode response = readResponse();
    768         if (response == MTP_RESPONSE_OK)
    769             result = true;
    770     }
    771 
    772 fail:
    773     ::close(fd);
    774     return result;
    775 }
    776 
    777 bool MtpDevice::sendRequest(MtpOperationCode operation) {
    778     ALOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
    779     mReceivedResponse = false;
    780     mRequest.setOperationCode(operation);
    781     if (mTransactionID > 0)
    782         mRequest.setTransactionID(mTransactionID++);
    783     int ret = mRequest.write(mRequestOut);
    784     mRequest.dump();
    785     return (ret > 0);
    786 }
    787 
    788 bool MtpDevice::sendData() {
    789     ALOGV("sendData\n");
    790     mData.setOperationCode(mRequest.getOperationCode());
    791     mData.setTransactionID(mRequest.getTransactionID());
    792     int ret = mData.write(mRequestOut);
    793     mData.dump();
    794     return (ret > 0);
    795 }
    796 
    797 bool MtpDevice::readData() {
    798     mData.reset();
    799     int ret = mData.read(mRequestIn1);
    800     ALOGV("readData returned %d\n", ret);
    801     if (ret >= MTP_CONTAINER_HEADER_SIZE) {
    802         if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
    803             ALOGD("got response packet instead of data packet");
    804             // we got a response packet rather than data
    805             // copy it to mResponse
    806             mResponse.copyFrom(mData);
    807             mReceivedResponse = true;
    808             return false;
    809         }
    810         mData.dump();
    811         return true;
    812     }
    813     else {
    814         ALOGV("readResponse failed\n");
    815         return false;
    816     }
    817 }
    818 
    819 bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
    820     mData.setOperationCode(operation);
    821     mData.setTransactionID(mRequest.getTransactionID());
    822     return (!mData.writeDataHeader(mRequestOut, dataLength));
    823 }
    824 
    825 MtpResponseCode MtpDevice::readResponse() {
    826     ALOGV("readResponse\n");
    827     if (mReceivedResponse) {
    828         mReceivedResponse = false;
    829         return mResponse.getResponseCode();
    830     }
    831     int ret = mResponse.read(mRequestIn1);
    832     // handle zero length packets, which might occur if the data transfer
    833     // ends on a packet boundary
    834     if (ret == 0)
    835         ret = mResponse.read(mRequestIn1);
    836     if (ret >= MTP_CONTAINER_HEADER_SIZE) {
    837         mResponse.dump();
    838         return mResponse.getResponseCode();
    839     } else {
    840         ALOGD("readResponse failed\n");
    841         return -1;
    842     }
    843 }
    844 
    845 }  // namespace android
    846