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