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