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, 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
475bool 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
501bool 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
514MtpObjectHandle 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
525MtpObjectHandle 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
536MtpObjectPropertyList* 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
553MtpProperty* 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
573MtpProperty* 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
594bool 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
681fail:
682    return result;
683}
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    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
781fail:
782    ::close(fd);
783    return result;
784}
785
786bool 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
797bool 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
806bool 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
828bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
829    mData.setOperationCode(operation);
830    mData.setTransactionID(mRequest.getTransactionID());
831    return (!mData.writeDataHeader(mRequestOut, dataLength));
832}
833
834MtpResponseCode 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