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