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