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