MtpDevice.cpp revision 81ca5ade77ea518aa21fdd7434d2db5df088a115
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
39namespace android {
40
41#if 0
42static 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
53MtpDevice* 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
184MtpDevice::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
205MtpDevice::~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
215void 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
231void MtpDevice::close() {
232    if (mDevice) {
233        usb_device_release_interface(mDevice, mInterface);
234        usb_device_close(mDevice);
235        mDevice = NULL;
236    }
237}
238
239void 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
281const char* MtpDevice::getDeviceName() {
282    if (mDevice)
283        return usb_device_get_name(mDevice);
284    else
285        return "???";
286}
287
288bool 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
309bool MtpDevice::closeSession() {
310    // FIXME
311    return true;
312}
313
314MtpDeviceInfo* 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
333MtpStorageIDList* 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
348MtpStorageInfo* 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
368MtpObjectHandleList* 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
387MtpObjectInfo* 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
409void* 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
424MtpObjectHandle 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, parent);
434
435    mData.reset();
436    mData.putUInt32(info->mStorageID);
437    mData.putUInt16(info->mFormat);
438    mData.putUInt16(info->mProtectionStatus);
439    mData.putUInt32(info->mCompressedSize);
440    mData.putUInt16(info->mThumbFormat);
441    mData.putUInt32(info->mThumbCompressedSize);
442    mData.putUInt32(info->mThumbPixWidth);
443    mData.putUInt32(info->mThumbPixHeight);
444    mData.putUInt32(info->mImagePixWidth);
445    mData.putUInt32(info->mImagePixHeight);
446    mData.putUInt32(info->mImagePixDepth);
447    mData.putUInt32(info->mParent);
448    mData.putUInt16(info->mAssociationType);
449    mData.putUInt32(info->mAssociationDesc);
450    mData.putUInt32(info->mSequenceNumber);
451    mData.putString(info->mName);
452
453    char created[100], modified[100];
454    formatDateTime(info->mDateCreated, created, sizeof(created));
455    formatDateTime(info->mDateModified, modified, sizeof(modified));
456
457    mData.putString(created);
458    mData.putString(modified);
459    if (info->mKeywords)
460        mData.putString(info->mKeywords);
461    else
462        mData.putEmptyString();
463
464   if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
465        MtpResponseCode ret = readResponse();
466        if (ret == MTP_RESPONSE_OK) {
467            info->mStorageID = mResponse.getParameter(1);
468            info->mParent = mResponse.getParameter(2);
469            info->mHandle = mResponse.getParameter(3);
470            return info->mHandle;
471        }
472    }
473    return (MtpObjectHandle)-1;
474}
475
476bool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) {
477    Mutex::Autolock autoLock(mMutex);
478
479    int remaining = info->mCompressedSize;
480    mRequest.reset();
481    mRequest.setParameter(1, info->mHandle);
482    if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
483        // send data header
484        writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
485
486        char buffer[65536];
487        while (remaining > 0) {
488            int count = read(srcFD, buffer, sizeof(buffer));
489            if (count > 0) {
490                int written = mData.write(mRequestOut, buffer, count);
491                // FIXME check error
492                remaining -= count;
493            } else {
494                break;
495            }
496        }
497    }
498    MtpResponseCode ret = readResponse();
499    return (remaining == 0 && ret == MTP_RESPONSE_OK);
500}
501
502bool MtpDevice::deleteObject(MtpObjectHandle handle) {
503    Mutex::Autolock autoLock(mMutex);
504
505    mRequest.reset();
506    mRequest.setParameter(1, handle);
507    if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) {
508        MtpResponseCode ret = readResponse();
509        if (ret == MTP_RESPONSE_OK)
510            return true;
511    }
512    return false;
513}
514
515MtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) {
516    MtpObjectInfo* info = getObjectInfo(handle);
517    if (info) {
518        MtpObjectHandle parent = info->mParent;
519        delete info;
520        return parent;
521    } else {
522        return -1;
523    }
524}
525
526MtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) {
527    MtpObjectInfo* info = getObjectInfo(handle);
528    if (info) {
529        MtpObjectHandle storageId = info->mStorageID;
530        delete info;
531        return storageId;
532    } else {
533        return -1;
534    }
535}
536
537MtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) {
538    Mutex::Autolock autoLock(mMutex);
539
540    mRequest.reset();
541    mRequest.setParameter(1, format);
542    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED))
543        return NULL;
544    if (!readData())
545        return NULL;
546    MtpResponseCode ret = readResponse();
547    if (ret == MTP_RESPONSE_OK) {
548        return mData.getAUInt16();
549    }
550    return NULL;
551
552}
553
554MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
555    Mutex::Autolock autoLock(mMutex);
556
557    mRequest.reset();
558    mRequest.setParameter(1, code);
559    if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC))
560        return NULL;
561    if (!readData())
562        return NULL;
563    MtpResponseCode ret = readResponse();
564    if (ret == MTP_RESPONSE_OK) {
565        MtpProperty* property = new MtpProperty;
566        if (property->read(mData))
567            return property;
568        else
569            delete property;
570    }
571    return NULL;
572}
573
574MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) {
575    Mutex::Autolock autoLock(mMutex);
576
577    mRequest.reset();
578    mRequest.setParameter(1, code);
579    mRequest.setParameter(2, format);
580    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC))
581        return NULL;
582    if (!readData())
583        return NULL;
584    MtpResponseCode ret = readResponse();
585    if (ret == MTP_RESPONSE_OK) {
586        MtpProperty* property = new MtpProperty;
587        if (property->read(mData))
588            return property;
589        else
590            delete property;
591    }
592    return NULL;
593}
594
595bool MtpDevice::readObject(MtpObjectHandle handle,
596        bool (* callback)(void* data, int offset, int length, void* clientData),
597        size_t objectSize, void* clientData) {
598    Mutex::Autolock autoLock(mMutex);
599    bool result = false;
600
601    mRequest.reset();
602    mRequest.setParameter(1, handle);
603    if (sendRequest(MTP_OPERATION_GET_OBJECT)
604            && mData.readDataHeader(mRequestIn1)) {
605        uint32_t length = mData.getContainerLength();
606        if (length - MTP_CONTAINER_HEADER_SIZE != objectSize) {
607            ALOGE("readObject error objectSize: %d, length: %d",
608                    objectSize, length);
609            goto fail;
610        }
611        length -= MTP_CONTAINER_HEADER_SIZE;
612        uint32_t remaining = length;
613        int offset = 0;
614
615        int initialDataLength = 0;
616        void* initialData = mData.getData(initialDataLength);
617        if (initialData) {
618            if (initialDataLength > 0) {
619                if (!callback(initialData, 0, initialDataLength, clientData))
620                    goto fail;
621                remaining -= initialDataLength;
622                offset += initialDataLength;
623            }
624            free(initialData);
625        }
626
627        // USB reads greater than 16K don't work
628        char buffer1[16384], buffer2[16384];
629        mRequestIn1->buffer = buffer1;
630        mRequestIn2->buffer = buffer2;
631        struct usb_request* req = mRequestIn1;
632        void* writeBuffer = NULL;
633        int writeLength = 0;
634
635        while (remaining > 0 || writeBuffer) {
636            if (remaining > 0) {
637                // queue up a read request
638                req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
639                if (mData.readDataAsync(req)) {
640                    ALOGE("readDataAsync failed");
641                    goto fail;
642                }
643            } else {
644                req = NULL;
645            }
646
647            if (writeBuffer) {
648                // write previous buffer
649                if (!callback(writeBuffer, offset, writeLength, clientData)) {
650                    ALOGE("write failed");
651                    // wait for pending read before failing
652                    if (req)
653                        mData.readDataWait(mDevice);
654                    goto fail;
655                }
656                offset += writeLength;
657                writeBuffer = NULL;
658            }
659
660            // wait for read to complete
661            if (req) {
662                int read = mData.readDataWait(mDevice);
663                if (read < 0)
664                    goto fail;
665
666                if (read > 0) {
667                    writeBuffer = req->buffer;
668                    writeLength = read;
669                    remaining -= read;
670                    req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
671                } else {
672                    writeBuffer = NULL;
673                }
674            }
675        }
676
677        MtpResponseCode response = readResponse();
678        if (response == MTP_RESPONSE_OK)
679            result = true;
680    }
681
682fail:
683    return result;
684}
685
686// reads the object's data and writes it to the specified file path
687bool 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    bool result = readObject(handle, fd);
702    ::close(fd);
703    return result;
704}
705
706bool MtpDevice::readObject(MtpObjectHandle handle, int fd) {
707    ALOGD("readObject: %d", fd);
708
709    Mutex::Autolock autoLock(mMutex);
710
711    mRequest.reset();
712    mRequest.setParameter(1, handle);
713    if (sendRequest(MTP_OPERATION_GET_OBJECT) && mData.readDataHeader(mRequestIn1)) {
714        uint32_t length = mData.getContainerLength();
715        if (length < MTP_CONTAINER_HEADER_SIZE) {
716            ALOGE("Invalid container length.");
717            return false;
718        }
719        length -= MTP_CONTAINER_HEADER_SIZE;
720        uint32_t remaining = length;
721
722        bool writingError = false;
723        int initialDataLength = 0;
724        void* initialData = mData.getData(initialDataLength);
725        if (initialData) {
726            if (initialDataLength > 0) {
727                if (write(fd, initialData, initialDataLength) != initialDataLength) {
728                    ALOGE("Failed to write initial data.");
729                    writingError = true;
730                }
731                remaining -= initialDataLength;
732            }
733            free(initialData);
734        }
735
736        // USB reads greater than 16K don't work
737        char buffer1[16384], buffer2[16384];
738        mRequestIn1->buffer = buffer1;
739        mRequestIn2->buffer = buffer2;
740        struct usb_request* req = mRequestIn1;
741        void* writeBuffer = NULL;
742        int writeLength = 0;
743
744        while (remaining > 0 || writeBuffer) {
745            if (remaining > 0) {
746                // queue up a read request
747                req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
748                if (mData.readDataAsync(req)) {
749                    ALOGE("readDataAsync failed");
750                    return false;
751                }
752            } else {
753                req = NULL;
754            }
755
756            if (writeBuffer && !writingError) {
757                // write previous buffer
758                if (write(fd, writeBuffer, writeLength) != writeLength) {
759                    writingError = true;
760                }
761            }
762            writeBuffer = NULL;
763
764            // wait for read to complete
765            if (req) {
766                int read = mData.readDataWait(mDevice);
767                if (read < 0) {
768                    ALOGE("readDataWait failed.");
769                    return false;
770                }
771
772                if (read > 0) {
773                    writeBuffer = req->buffer;
774                    writeLength = read;
775                    remaining -= read;
776                    req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
777                } else {
778                    writeBuffer = NULL;
779                }
780            }
781        }
782
783        MtpResponseCode response = readResponse();
784        return response == MTP_RESPONSE_OK && !writingError;
785    }
786
787    return false;
788}
789
790bool MtpDevice::sendRequest(MtpOperationCode operation) {
791    ALOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
792    mReceivedResponse = false;
793    mRequest.setOperationCode(operation);
794    if (mTransactionID > 0)
795        mRequest.setTransactionID(mTransactionID++);
796    int ret = mRequest.write(mRequestOut);
797    mRequest.dump();
798    return (ret > 0);
799}
800
801bool MtpDevice::sendData() {
802    ALOGV("sendData\n");
803    mData.setOperationCode(mRequest.getOperationCode());
804    mData.setTransactionID(mRequest.getTransactionID());
805    int ret = mData.write(mRequestOut);
806    mData.dump();
807    return (ret >= 0);
808}
809
810bool MtpDevice::readData() {
811    mData.reset();
812    int ret = mData.read(mRequestIn1);
813    ALOGV("readData returned %d\n", ret);
814    if (ret >= MTP_CONTAINER_HEADER_SIZE) {
815        if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
816            ALOGD("got response packet instead of data packet");
817            // we got a response packet rather than data
818            // copy it to mResponse
819            mResponse.copyFrom(mData);
820            mReceivedResponse = true;
821            return false;
822        }
823        mData.dump();
824        return true;
825    }
826    else {
827        ALOGV("readResponse failed\n");
828        return false;
829    }
830}
831
832bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
833    mData.setOperationCode(operation);
834    mData.setTransactionID(mRequest.getTransactionID());
835    return (!mData.writeDataHeader(mRequestOut, dataLength));
836}
837
838MtpResponseCode MtpDevice::readResponse() {
839    ALOGV("readResponse\n");
840    if (mReceivedResponse) {
841        mReceivedResponse = false;
842        return mResponse.getResponseCode();
843    }
844    int ret = mResponse.read(mRequestIn1);
845    // handle zero length packets, which might occur if the data transfer
846    // ends on a packet boundary
847    if (ret == 0)
848        ret = mResponse.read(mRequestIn1);
849    if (ret >= MTP_CONTAINER_HEADER_SIZE) {
850        mResponse.dump();
851        return mResponse.getResponseCode();
852    } else {
853        ALOGD("readResponse failed\n");
854        return -1;
855    }
856}
857
858}  // namespace android
859