15ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood/*
25ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * Copyright (C) 2010 The Android Open Source Project
35ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood *
45ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
55ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * you may not use this file except in compliance with the License.
65ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * You may obtain a copy of the License at
75ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood *
85ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
95ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood *
105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * Unless required by applicable law or agreed to in writing, software
115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
125ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * See the License for the specific language governing permissions and
145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * limitations under the License.
155ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood */
165ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
17a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood#define LOG_TAG "MtpDevice"
18b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood
19b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpDebug.h"
20b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpDevice.h"
21b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpDeviceInfo.h"
224fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono#include "MtpEventPacket.h"
23b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpObjectInfo.h"
24b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpProperty.h"
25b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpStorageInfo.h"
26b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpStringBuffer.h"
270cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood#include "MtpUtils.h"
28a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood
295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <stdio.h>
305ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <stdlib.h>
315ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <sys/types.h>
325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <sys/ioctl.h>
335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <sys/stat.h>
345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <fcntl.h>
355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <errno.h>
360cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood#include <endian.h>
375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <usbhost/usbhost.h>
395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodnamespace android {
415ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
426e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkivnamespace {
436e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv
446e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkivstatic constexpr int USB_CONTROL_TRANSFER_TIMEOUT_MS = 200;
456e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv
466e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv}  // namespace
476e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv
48d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#if 0
4923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodstatic bool isMtpDevice(uint16_t vendor, uint16_t product) {
5023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    // Sandisk Sansa Fuze
5123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    if (vendor == 0x0781 && product == 0x74c2)
5223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood        return true;
5323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    // Samsung YP-Z5
5423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    if (vendor == 0x04e8 && product == 0x503c)
5523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood        return true;
5623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    return false;
5723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood}
58d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#endif
5923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
604fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirononamespace {
614fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
624a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hironobool writeToFd(void* data, uint32_t /* unused_offset */, uint32_t length, void* clientData) {
634fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    const int fd = *static_cast<int*>(clientData);
644a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    const ssize_t result = write(fd, data, length);
654a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    if (result < 0) {
664a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono        return false;
674a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    }
684a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    return static_cast<uint32_t>(result) == length;
694fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono}
704fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
714a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono}  // namespace
724fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
7323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike LockwoodMtpDevice* MtpDevice::open(const char* deviceName, int fd) {
7423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    struct usb_device *device = usb_device_new(deviceName, fd);
7523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    if (!device) {
7629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("usb_device_new failed for %s", deviceName);
7723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood        return NULL;
7823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    }
7923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
8023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    struct usb_descriptor_header* desc;
8123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    struct usb_descriptor_iter iter;
8223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
8323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    usb_descriptor_iter_init(device, &iter);
8423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
8523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {
8623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood        if (desc->bDescriptorType == USB_DT_INTERFACE) {
8723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;
8823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
8923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            if (interface->bInterfaceClass == USB_CLASS_STILL_IMAGE &&
9023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                interface->bInterfaceSubClass == 1 && // Still Image Capture
9123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                interface->bInterfaceProtocol == 1)     // Picture Transfer Protocol (PIMA 15470)
9223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            {
936e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv                char* manufacturerName = usb_device_get_manufacturer_name(device,
946e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv                        USB_CONTROL_TRANSFER_TIMEOUT_MS);
956e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv                char* productName = usb_device_get_product_name(device,
966e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv                        USB_CONTROL_TRANSFER_TIMEOUT_MS);
97b8a805261bf0282e992d3608035e47d05a898710Steve Block                ALOGD("Found camera: \"%s\" \"%s\"\n", manufacturerName, productName);
9831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                free(manufacturerName);
9931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                free(productName);
10023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            } else if (interface->bInterfaceClass == 0xFF &&
10123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    interface->bInterfaceSubClass == 0xFF &&
10223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    interface->bInterfaceProtocol == 0) {
1036e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv                char* interfaceName = usb_device_get_string(device, interface->iInterface,
1046e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv                        USB_CONTROL_TRANSFER_TIMEOUT_MS);
10531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                if (!interfaceName) {
10623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    continue;
10731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                } else if (strcmp(interfaceName, "MTP")) {
10831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    free(interfaceName);
10931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    continue;
11031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                }
11131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                free(interfaceName);
11231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root
11323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                // Looks like an android style MTP device
1146e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv                char* manufacturerName = usb_device_get_manufacturer_name(device,
1156e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv                        USB_CONTROL_TRANSFER_TIMEOUT_MS);
1166e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv                char* productName = usb_device_get_product_name(device,
1176e08d93aa2194b084b90cd4fdd04148180deed77Vitalii Tomkiv                        USB_CONTROL_TRANSFER_TIMEOUT_MS);
118b8a805261bf0282e992d3608035e47d05a898710Steve Block                ALOGD("Found MTP device: \"%s\" \"%s\"\n", manufacturerName, productName);
11931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                free(manufacturerName);
12031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                free(productName);
121d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood            }
122d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#if 0
123d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood             else {
12423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                // look for special cased devices based on vendor/product ID
12523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                // we are doing this mainly for testing purposes
12623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                uint16_t vendor = usb_device_get_vendor_id(device);
12723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                uint16_t product = usb_device_get_product_id(device);
12823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                if (!isMtpDevice(vendor, product)) {
12923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    // not an MTP or PTP device
13023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    continue;
13123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                }
13223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                // request MTP OS string and descriptor
13323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                // some music players need to see this before entering MTP mode.
13423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                char buffer[256];
13523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                memset(buffer, 0, sizeof(buffer));
136f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood                int ret = usb_device_control_transfer(device,
13723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                        USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_STANDARD,
13823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                        USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | 0xEE,
139f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood                        0, buffer, sizeof(buffer), 0);
140f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood                printf("usb_device_control_transfer returned %d errno: %d\n", ret, errno);
14123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                if (ret > 0) {
14223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    printf("got MTP string %s\n", buffer);
143f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood                    ret = usb_device_control_transfer(device,
14423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                            USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, 1,
145f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood                            0, 4, buffer, sizeof(buffer), 0);
14623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    printf("OS descriptor got %d\n", ret);
14723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                } else {
14823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    printf("no MTP string\n");
14923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                }
15023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            }
151d6dabe95eb59c3d95f94825d08a6028bab06cbdcDaichi Hirono#else
152d6dabe95eb59c3d95f94825d08a6028bab06cbdcDaichi Hirono            else {
153d6dabe95eb59c3d95f94825d08a6028bab06cbdcDaichi Hirono                continue;
154d6dabe95eb59c3d95f94825d08a6028bab06cbdcDaichi Hirono            }
155d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#endif
15623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            // if we got here, then we have a likely MTP or PTP device
15723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
15823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            // interface should be followed by three endpoints
15923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            struct usb_endpoint_descriptor *ep;
16023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            struct usb_endpoint_descriptor *ep_in_desc = NULL;
16123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            struct usb_endpoint_descriptor *ep_out_desc = NULL;
16223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            struct usb_endpoint_descriptor *ep_intr_desc = NULL;
1638023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang            //USB3 add USB_DT_SS_ENDPOINT_COMP as companion descriptor;
1648023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang            struct usb_ss_ep_comp_descriptor *ep_ss_ep_comp_desc = NULL;
16523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            for (int i = 0; i < 3; i++) {
16623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
1678023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang                if (ep && ep->bDescriptorType == USB_DT_SS_ENDPOINT_COMP) {
1688023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang                    ALOGD("Descriptor type is USB_DT_SS_ENDPOINT_COMP for USB3 \n");
1698023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang                    ep_ss_ep_comp_desc = (usb_ss_ep_comp_descriptor*)ep;
1708023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang                    ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
1718023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang                 }
1728023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang
17323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) {
17429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("endpoints not found\n");
17531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    usb_device_close(device);
17623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    return NULL;
17723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                }
1788023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang
17923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
18023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
18123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                        ep_in_desc = ep;
18223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    else
18323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                        ep_out_desc = ep;
18423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                } else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT &&
18523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
18623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    ep_intr_desc = ep;
18723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                }
18823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            }
18923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) {
19029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("endpoints not found\n");
19131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                usb_device_close(device);
19223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                return NULL;
19323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            }
19423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
19533d58162896868f387416289c8b33266be0a3360Jaesung Chung            int ret = usb_device_claim_interface(device, interface->bInterfaceNumber);
19633d58162896868f387416289c8b33266be0a3360Jaesung Chung            if (ret && errno == EBUSY) {
19733d58162896868f387416289c8b33266be0a3360Jaesung Chung                // disconnect kernel driver and try again
19833d58162896868f387416289c8b33266be0a3360Jaesung Chung                usb_device_connect_kernel_driver(device, interface->bInterfaceNumber, false);
19933d58162896868f387416289c8b33266be0a3360Jaesung Chung                ret = usb_device_claim_interface(device, interface->bInterfaceNumber);
20033d58162896868f387416289c8b33266be0a3360Jaesung Chung            }
20133d58162896868f387416289c8b33266be0a3360Jaesung Chung            if (ret) {
20229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("usb_device_claim_interface failed errno: %d\n", errno);
20331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                usb_device_close(device);
20423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                return NULL;
20523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            }
20623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
20723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber,
20823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                        ep_in_desc, ep_out_desc, ep_intr_desc);
20923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            mtpDevice->initialize();
21023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            return mtpDevice;
21123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood        }
21223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    }
21323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
21423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    usb_device_close(device);
21529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block    ALOGE("device not found");
21623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    return NULL;
21723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood}
21823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
2195ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDevice::MtpDevice(struct usb_device* device, int interface,
22042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood            const struct usb_endpoint_descriptor *ep_in,
22142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood            const struct usb_endpoint_descriptor *ep_out,
22242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood            const struct usb_endpoint_descriptor *ep_intr)
2235ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    :   mDevice(device),
2245ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mInterface(interface),
22542d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood        mRequestIn1(NULL),
22642d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood        mRequestIn2(NULL),
22742d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood        mRequestOut(NULL),
22842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood        mRequestIntr(NULL),
2295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mDeviceInfo(NULL),
2305ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mSessionID(0),
231f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood        mTransactionID(0),
2328a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        mReceivedResponse(false),
2338a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        mProcessingEvent(false),
2348d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono        mCurrentEventHandle(0),
2358d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono        mLastSendObjectInfoTransactionID(0),
236d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono        mLastSendObjectInfoObjectHandle(0),
237d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono        mPacketDivisionMode(FIRST_PACKET_HAS_PAYLOAD)
2385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood{
23942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    mRequestIn1 = usb_request_new(device, ep_in);
24042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    mRequestIn2 = usb_request_new(device, ep_in);
24142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    mRequestOut = usb_request_new(device, ep_out);
24242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    mRequestIntr = usb_request_new(device, ep_intr);
2435ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
2445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
2455ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDevice::~MtpDevice() {
2465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    close();
2473ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn    for (size_t i = 0; i < mDeviceProperties.size(); i++)
248a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        delete mDeviceProperties[i];
24942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    usb_request_free(mRequestIn1);
25042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    usb_request_free(mRequestIn2);
25142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    usb_request_free(mRequestOut);
25242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    usb_request_free(mRequestIntr);
2535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
2545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
2555ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid MtpDevice::initialize() {
2565ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    openSession();
2575ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mDeviceInfo = getDeviceInfo();
2585ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (mDeviceInfo) {
259a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        if (mDeviceInfo->mDeviceProperties) {
260a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood            int count = mDeviceInfo->mDeviceProperties->size();
261a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood            for (int i = 0; i < count; i++) {
262a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
263a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                MtpProperty* property = getDevicePropDesc(propCode);
2640c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                if (property)
265bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang                    mDeviceProperties.push_back(property);
266a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood            }
267a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        }
2685ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
2695ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
2705ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
2715ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid MtpDevice::close() {
2725ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (mDevice) {
2735ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        usb_device_release_interface(mDevice, mInterface);
2745ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        usb_device_close(mDevice);
2755ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mDevice = NULL;
2765ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
2775ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
2785ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
2790c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwoodvoid MtpDevice::print() {
2800269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang    if (!mDeviceInfo)
2810269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang        return;
2820c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood
2830269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang    mDeviceInfo->print();
2840269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang
2850269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang    if (mDeviceInfo->mDeviceProperties) {
2860269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang        ALOGI("***** DEVICE PROPERTIES *****\n");
2870269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang        int count = mDeviceInfo->mDeviceProperties->size();
2880269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang        for (int i = 0; i < count; i++) {
2890269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang            MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
2900269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang            MtpProperty* property = getDevicePropDesc(propCode);
2910269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang            if (property) {
2920269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang                property->print();
2930269068cb60dd68addfa5699664f04b376a82472Yunlian Jiang                delete property;
2940c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood            }
2950c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood        }
2960c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood    }
2970c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood
2980c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood    if (mDeviceInfo->mPlaybackFormats) {
299df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("***** OBJECT PROPERTIES *****\n");
3000c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood        int count = mDeviceInfo->mPlaybackFormats->size();
3010c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood        for (int i = 0; i < count; i++) {
3020c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood            MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i];
303df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format));
3040c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood            MtpObjectPropertyList* props = getObjectPropsSupported(format);
3050c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood            if (props) {
3063ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn                for (size_t j = 0; j < props->size(); j++) {
3070c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                    MtpObjectProperty prop = (*props)[j];
30899e393a39a31bfbdeb435462939519e2d0279433Mike Lockwood                    MtpProperty* property = getObjectPropDesc(prop, format);
30931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    if (property) {
3100c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                        property->print();
31131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                        delete property;
31231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    } else {
31329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                        ALOGE("could not fetch property: %s",
3140c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                                MtpDebug::getObjectPropCodeName(prop));
31531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    }
3160c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                }
3170c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood            }
3180c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood        }
3190c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood    }
3200c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood}
3210c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood
3225ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodconst char* MtpDevice::getDeviceName() {
3235ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (mDevice)
3245ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return usb_device_get_name(mDevice);
3255ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    else
3265ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return "???";
3275ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
3285ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::openSession() {
330bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
3310cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mSessionID = 0;
3335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mTransactionID = 0;
3345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpSessionID newSession = 1;
3355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
3365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(1, newSession);
3375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_OPEN_SESSION))
3385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return false;
3395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
3405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN)
3415ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        newSession = mResponse.getParameter(1);
3425ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    else if (ret != MTP_RESPONSE_OK)
3435ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return false;
3445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3455ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mSessionID = newSession;
3465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mTransactionID = 1;
3475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return true;
3485ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
3495ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3505ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::closeSession() {
3515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    // FIXME
3525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return true;
3535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
3545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3555ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDeviceInfo* MtpDevice::getDeviceInfo() {
356bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
3570cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3585ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
3595ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO))
3605ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3615ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
3625ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3635ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
3645ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
3655ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        MtpDeviceInfo* info = new MtpDeviceInfo;
366ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        if (info->read(mData))
367ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            return info;
368ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        else
369ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            delete info;
3705ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
3715ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
3725ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
3735ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3745ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageIDList* MtpDevice::getStorageIDs() {
375bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
3760cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3775ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
3785ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS))
3795ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3805ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
3815ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3825ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
3835ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
3845ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return mData.getAUInt32();
3855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
3865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
3875ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
3885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3895ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
390bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
3910cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3925ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
3935ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(1, storageID);
3945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO))
3955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
3975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3985ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
3995ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
4005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        MtpStorageInfo* info = new MtpStorageInfo(storageID);
401ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        if (info->read(mData))
402ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            return info;
403ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        else
404ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            delete info;
4055ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
4065ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
4075ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
4085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
4095ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
4105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood            MtpObjectFormat format, MtpObjectHandle parent) {
411bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
4120cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
4145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(1, storageID);
4155ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(2, format);
4165ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(3, parent);
4175ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES))
4185ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
4195ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
4205ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
4215ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
4225ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
4235ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return mData.getAUInt32();
4245ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
4255ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
4265ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
4275ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
4285ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
429bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
4300cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4316afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    // FIXME - we might want to add some caching here
4326afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood
4335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
4345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(1, handle);
4355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO))
4365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
4375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
4385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
4395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
4405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
4415ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        MtpObjectInfo* info = new MtpObjectInfo(handle);
442ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        if (info->read(mData))
443ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            return info;
444ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        else
445ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            delete info;
4465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
4475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
4485ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
4495ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
4503e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwoodvoid* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) {
451bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
4520cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4533e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    mRequest.reset();
4543e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    mRequest.setParameter(1, handle);
4553e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
4563e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood        MtpResponseCode ret = readResponse();
4573e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood        if (ret == MTP_RESPONSE_OK) {
4584fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            return mData.getData(&outLength);
4593e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood        }
4603e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    }
4613e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    outLength = 0;
4623e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    return NULL;
4636afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood}
4646afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood
4650cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike LockwoodMtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) {
466bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
4670cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4680cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mRequest.reset();
4690cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    MtpObjectHandle parent = info->mParent;
4700cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    if (parent == 0)
4710cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        parent = MTP_PARENT_ROOT;
4720cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4730cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mRequest.setParameter(1, info->mStorageID);
47464c948bf5041fdfe391553315c9d028e1ee56382Tomasz Mikolajewski    mRequest.setParameter(2, parent);
4750cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
47664c948bf5041fdfe391553315c9d028e1ee56382Tomasz Mikolajewski    mData.reset();
4770cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mStorageID);
4780cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt16(info->mFormat);
4790cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt16(info->mProtectionStatus);
4800cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mCompressedSize);
4810cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt16(info->mThumbFormat);
4820cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mThumbCompressedSize);
4830cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mThumbPixWidth);
4840cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mThumbPixHeight);
4850cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mImagePixWidth);
4860cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mImagePixHeight);
4870cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mImagePixDepth);
4880cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mParent);
4890cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt16(info->mAssociationType);
4900cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mAssociationDesc);
4910cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mSequenceNumber);
4920cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putString(info->mName);
4930cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4940cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    char created[100], modified[100];
4950cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    formatDateTime(info->mDateCreated, created, sizeof(created));
4960cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    formatDateTime(info->mDateModified, modified, sizeof(modified));
4970cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4980cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putString(created);
4990cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putString(modified);
5000cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    if (info->mKeywords)
5010cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        mData.putString(info->mKeywords);
5020cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    else
5030cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        mData.putEmptyString();
5040cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
5050cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood   if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
5060cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        MtpResponseCode ret = readResponse();
5070cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        if (ret == MTP_RESPONSE_OK) {
5088d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono            mLastSendObjectInfoTransactionID = mRequest.getTransactionID();
5098d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono            mLastSendObjectInfoObjectHandle = mResponse.getParameter(3);
5100cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            info->mStorageID = mResponse.getParameter(1);
5110cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            info->mParent = mResponse.getParameter(2);
5120cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            info->mHandle = mResponse.getParameter(3);
5130cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            return info->mHandle;
5140cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        }
5150cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
5160cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    return (MtpObjectHandle)-1;
5170cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood}
5180cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
519532b4f23c7e08fdae9fff189c4b565f6216ffd2aTomasz Mikolajewskibool MtpDevice::sendObject(MtpObjectHandle handle, int size, int srcFD) {
520bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
5210cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
5228d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono    if (mLastSendObjectInfoTransactionID + 1 != mTransactionID ||
5238d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono            mLastSendObjectInfoObjectHandle != handle) {
5248d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono        ALOGE("A sendObject request must follow the sendObjectInfo request.");
5258d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono        return false;
5268d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono    }
5278d20945c08dfdd85c252c8ba92d197bf1bd2b208Daichi Hirono
5280cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mRequest.reset();
5290cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
530d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono        mData.setOperationCode(mRequest.getOperationCode());
531d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono        mData.setTransactionID(mRequest.getTransactionID());
532d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono        const int writeResult = mData.write(mRequestOut, mPacketDivisionMode, srcFD, size);
533d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono        const MtpResponseCode ret = readResponse();
534d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono        return ret == MTP_RESPONSE_OK && writeResult > 0;
5350cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
536d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono    return false;
5370cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood}
5380cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
5396afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwoodbool MtpDevice::deleteObject(MtpObjectHandle handle) {
540bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
5410cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
5426afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    mRequest.reset();
5436afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    mRequest.setParameter(1, handle);
5446afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) {
5456afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        MtpResponseCode ret = readResponse();
5466afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        if (ret == MTP_RESPONSE_OK)
5476afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood            return true;
5486afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    }
5496afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    return false;
5506afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood}
5516afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood
5526afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) {
5536afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    MtpObjectInfo* info = getObjectInfo(handle);
55431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root    if (info) {
55531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root        MtpObjectHandle parent = info->mParent;
55631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root        delete info;
55731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root        return parent;
55831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root    } else {
5596afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        return -1;
56031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root    }
5616afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood}
5623e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood
5636afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) {
5646afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    MtpObjectInfo* info = getObjectInfo(handle);
56531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root    if (info) {
56631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root        MtpObjectHandle storageId = info->mStorageID;
56731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root        delete info;
56831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root        return storageId;
56931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root    } else {
5706afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        return -1;
57131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root    }
5723e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood}
5733e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood
57498693f674125484de8873d969c209276a6dd604bMike LockwoodMtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) {
575bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
57698693f674125484de8873d969c209276a6dd604bMike Lockwood
57798693f674125484de8873d969c209276a6dd604bMike Lockwood    mRequest.reset();
57898693f674125484de8873d969c209276a6dd604bMike Lockwood    mRequest.setParameter(1, format);
57998693f674125484de8873d969c209276a6dd604bMike Lockwood    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED))
58098693f674125484de8873d969c209276a6dd604bMike Lockwood        return NULL;
58198693f674125484de8873d969c209276a6dd604bMike Lockwood    if (!readData())
58298693f674125484de8873d969c209276a6dd604bMike Lockwood        return NULL;
58398693f674125484de8873d969c209276a6dd604bMike Lockwood    MtpResponseCode ret = readResponse();
58498693f674125484de8873d969c209276a6dd604bMike Lockwood    if (ret == MTP_RESPONSE_OK) {
58598693f674125484de8873d969c209276a6dd604bMike Lockwood        return mData.getAUInt16();
58698693f674125484de8873d969c209276a6dd604bMike Lockwood    }
58798693f674125484de8873d969c209276a6dd604bMike Lockwood    return NULL;
58898693f674125484de8873d969c209276a6dd604bMike Lockwood
58998693f674125484de8873d969c209276a6dd604bMike Lockwood}
59098693f674125484de8873d969c209276a6dd604bMike Lockwood
591a6c490b8b2d96ebaab632286029463f932ae3b6bMike LockwoodMtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
592bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
5930cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
594a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    mRequest.reset();
595a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    mRequest.setParameter(1, code);
596a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC))
597a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        return NULL;
598a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    if (!readData())
599a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        return NULL;
600a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    MtpResponseCode ret = readResponse();
601a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    if (ret == MTP_RESPONSE_OK) {
602a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        MtpProperty* property = new MtpProperty;
603ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        if (property->read(mData))
604ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            return property;
605ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        else
606ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            delete property;
607a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    }
608a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    return NULL;
609a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood}
610a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood
61199e393a39a31bfbdeb435462939519e2d0279433Mike LockwoodMtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) {
612bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
61398693f674125484de8873d969c209276a6dd604bMike Lockwood
61498693f674125484de8873d969c209276a6dd604bMike Lockwood    mRequest.reset();
61598693f674125484de8873d969c209276a6dd604bMike Lockwood    mRequest.setParameter(1, code);
61699e393a39a31bfbdeb435462939519e2d0279433Mike Lockwood    mRequest.setParameter(2, format);
61798693f674125484de8873d969c209276a6dd604bMike Lockwood    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC))
61898693f674125484de8873d969c209276a6dd604bMike Lockwood        return NULL;
61998693f674125484de8873d969c209276a6dd604bMike Lockwood    if (!readData())
62098693f674125484de8873d969c209276a6dd604bMike Lockwood        return NULL;
62166a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono    const MtpResponseCode ret = readResponse();
62298693f674125484de8873d969c209276a6dd604bMike Lockwood    if (ret == MTP_RESPONSE_OK) {
62398693f674125484de8873d969c209276a6dd604bMike Lockwood        MtpProperty* property = new MtpProperty;
624ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        if (property->read(mData))
625ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            return property;
626ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        else
627ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            delete property;
62898693f674125484de8873d969c209276a6dd604bMike Lockwood    }
62998693f674125484de8873d969c209276a6dd604bMike Lockwood    return NULL;
63098693f674125484de8873d969c209276a6dd604bMike Lockwood}
63198693f674125484de8873d969c209276a6dd604bMike Lockwood
63266a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hironobool MtpDevice::getObjectPropValue(MtpObjectHandle handle, MtpProperty* property) {
63366a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono    if (property == nullptr)
63466a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono        return false;
63566a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono
636bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
63766a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono
63866a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono    mRequest.reset();
63966a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono    mRequest.setParameter(1, handle);
64066a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono    mRequest.setParameter(2, property->getPropertyCode());
64166a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_VALUE))
64266a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono        return false;
64366a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono    if (!readData())
64466a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono        return false;
64566a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono    if (readResponse() != MTP_RESPONSE_OK)
64666a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono        return false;
64766a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono    property->setCurrentValue(mData);
64866a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono    return true;
64966a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono}
65066a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono
65123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodbool MtpDevice::readObject(MtpObjectHandle handle,
6524fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                           ReadObjectCallback callback,
6534a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                           uint32_t expectedLength,
6544fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                           void* clientData) {
6554fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    return readObjectInternal(handle, callback, &expectedLength, clientData);
65623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood}
65723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
658b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood// reads the object's data and writes it to the specified file path
65927afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwoodbool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
660b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("readObject: %s", destPath);
661af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich    int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
662b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood    if (fd < 0) {
66329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("open failed for %s", destPath);
664b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood        return false;
6650cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
6660cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
66727afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood    fchown(fd, getuid(), group);
66827afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood    // set permissions
66927afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood    int mask = umask(0);
67027afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood    fchmod(fd, perm);
67127afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood    umask(mask);
67227afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood
673025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski    bool result = readObject(handle, fd);
674025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski    ::close(fd);
675025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski    return result;
676025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski}
677025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski
678025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewskibool MtpDevice::readObject(MtpObjectHandle handle, int fd) {
679025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski    ALOGD("readObject: %d", fd);
6804fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    return readObjectInternal(handle, writeToFd, NULL /* expected size */, &fd);
6814fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono}
682025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski
6834fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hironobool MtpDevice::readObjectInternal(MtpObjectHandle handle,
6844fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                                   ReadObjectCallback callback,
6854a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                                   const uint32_t* expectedLength,
6864fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                                   void* clientData) {
687bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
6880cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
689b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood    mRequest.reset();
690b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood    mRequest.setParameter(1, handle);
6914fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    if (!sendRequest(MTP_OPERATION_GET_OBJECT)) {
6924fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        ALOGE("Failed to send a read request.");
6934fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        return false;
6944fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    }
6954fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
6964a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    return readData(callback, expectedLength, nullptr, clientData);
6974a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono}
6984a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono
6994a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hironobool MtpDevice::readData(ReadObjectCallback callback,
7004a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                            const uint32_t* expectedLength,
7014a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                            uint32_t* writtenSize,
7024a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                            void* clientData) {
7034fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    if (!mData.readDataHeader(mRequestIn1)) {
7044fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        ALOGE("Failed to read header.");
7054fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        return false;
7064fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    }
7074fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
708d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono    // If object size 0 byte, the remote device may reply a response packet without sending any data
709d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono    // packets.
710a04e6fa61391f1ef64266579760f315c6b3e70b9Daichi Hirono    if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
711a04e6fa61391f1ef64266579760f315c6b3e70b9Daichi Hirono        mResponse.copyFrom(mData);
712a04e6fa61391f1ef64266579760f315c6b3e70b9Daichi Hirono        return mResponse.getResponseCode() == MTP_RESPONSE_OK;
713a04e6fa61391f1ef64266579760f315c6b3e70b9Daichi Hirono    }
714a04e6fa61391f1ef64266579760f315c6b3e70b9Daichi Hirono
7154fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    const uint32_t fullLength = mData.getContainerLength();
7164a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    if (fullLength < MTP_CONTAINER_HEADER_SIZE) {
7174a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono        ALOGE("fullLength is too short: %d", fullLength);
7184a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono        return false;
7194a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    }
7204a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    const uint32_t length = fullLength - MTP_CONTAINER_HEADER_SIZE;
7214a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    if (expectedLength && length != *expectedLength) {
7224fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        ALOGE("readObject error length: %d", fullLength);
7234fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        return false;
7244fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    }
7254fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
7264fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    uint32_t offset = 0;
7274fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    bool writingError = false;
728b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood
7294fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    {
730b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood        int initialDataLength = 0;
7314fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        void* const initialData = mData.getData(&initialDataLength);
732d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono        if (fullLength > MTP_CONTAINER_HEADER_SIZE && initialDataLength == 0) {
733d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono            // According to the MTP spec, the responder (MTP device) can choose two ways of sending
734d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono            // data. a) The first packet contains the head and as much of the payload as possible
735d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono            // b) The first packet contains only the header. The initiator (MTP host) needs
736d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono            // to remember which way the responder used, and send upcoming data in the same way.
737d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono            ALOGD("Found short packet that contains only a header.");
738d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono            mPacketDivisionMode = FIRST_PACKET_ONLY_HEADER;
739d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono        }
740b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood        if (initialData) {
741b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood            if (initialDataLength > 0) {
7424fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                if (!callback(initialData, offset, initialDataLength, clientData)) {
74381ca5ade77ea518aa21fdd7434d2db5df088a115Daichi Hirono                    ALOGE("Failed to write initial data.");
74481ca5ade77ea518aa21fdd7434d2db5df088a115Daichi Hirono                    writingError = true;
74531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                }
7464fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                offset += initialDataLength;
7470cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            }
748b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood            free(initialData);
7490cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        }
7504fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    }
7510cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
7524fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    // USB reads greater than 16K don't work.
7534fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    char buffer1[MTP_BUFFER_SIZE], buffer2[MTP_BUFFER_SIZE];
7544fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    mRequestIn1->buffer = buffer1;
7554fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    mRequestIn2->buffer = buffer2;
7564fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    struct usb_request* req = NULL;
7574fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
7584fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    while (offset < length) {
7594fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        // Wait for previous read to complete.
76042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood        void* writeBuffer = NULL;
761b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood        int writeLength = 0;
7624fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        if (req) {
7634fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            const int read = mData.readDataWait(mDevice);
7644fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            if (read < 0) {
7654fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                ALOGE("readDataWait failed.");
7664fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                return false;
7670cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            }
7684fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            writeBuffer = req->buffer;
7694fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            writeLength = read;
7704fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        }
7710cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
7724fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        // Request to read next chunk.
7734fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        const uint32_t nextOffset = offset + writeLength;
7744fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        if (nextOffset < length) {
7754fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            // Queue up a read request.
7764fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            const size_t remaining = length - nextOffset;
7774fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
7784a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono            req->buffer_length = remaining > MTP_BUFFER_SIZE ?
7794a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                    static_cast<size_t>(MTP_BUFFER_SIZE) : remaining;
7804fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            if (mData.readDataAsync(req) != 0) {
7814fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                ALOGE("readDataAsync failed");
7824fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                return false;
783b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood            }
7844fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        }
7850cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
7864fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        // Write previous buffer.
7874fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        if (writeBuffer && !writingError) {
7884fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            if (!callback(writeBuffer, offset, writeLength, clientData)) {
7894fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                ALOGE("write failed");
7904fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                writingError = true;
791b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood            }
792b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood        }
7934fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        offset = nextOffset;
7940cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
795b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood
7964a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    if (writtenSize) {
7974a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono        *writtenSize = length;
7984a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    }
7994a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono
8004a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    return readResponse() == MTP_RESPONSE_OK;
8014a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono}
8024a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono
8034a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hironobool MtpDevice::readPartialObject(MtpObjectHandle handle,
8044a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                                  uint32_t offset,
8054a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                                  uint32_t size,
8064a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                                  uint32_t *writtenSize,
8074a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                                  ReadObjectCallback callback,
8084a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono                                  void* clientData) {
809bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
8104a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono
8114a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    mRequest.reset();
8124a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    mRequest.setParameter(1, handle);
8134a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    mRequest.setParameter(2, offset);
8144a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    mRequest.setParameter(3, size);
8154a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    if (!sendRequest(MTP_OPERATION_GET_PARTIAL_OBJECT)) {
8164a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono        ALOGE("Failed to send a read request.");
8174a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono        return false;
8184a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono    }
819610d4a125f0144ec4915e5cef9f53e431cb117afDaichi Hirono    // The expected size is null because it requires the exact number of bytes to read though
820610d4a125f0144ec4915e5cef9f53e431cb117afDaichi Hirono    // MTP_OPERATION_GET_PARTIAL_OBJECT allows devices to return shorter length of bytes than
821610d4a125f0144ec4915e5cef9f53e431cb117afDaichi Hirono    // requested. Destination's buffer length should be checked in |callback|.
822326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono    return readData(callback, nullptr /* expected size */, writtenSize, clientData);
823326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono}
824326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono
825326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hironobool MtpDevice::readPartialObject64(MtpObjectHandle handle,
826326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono                                    uint64_t offset,
827326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono                                    uint32_t size,
828326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono                                    uint32_t *writtenSize,
829326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono                                    ReadObjectCallback callback,
830326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono                                    void* clientData) {
831bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mMutex);
832326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono
833326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono    mRequest.reset();
834326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono    mRequest.setParameter(1, handle);
835326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono    mRequest.setParameter(2, 0xffffffff & offset);
836326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono    mRequest.setParameter(3, 0xffffffff & (offset >> 32));
837326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono    mRequest.setParameter(4, size);
838326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono    if (!sendRequest(MTP_OPERATION_GET_PARTIAL_OBJECT_64)) {
839326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono        ALOGE("Failed to send a read request.");
840326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono        return false;
841326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono    }
842610d4a125f0144ec4915e5cef9f53e431cb117afDaichi Hirono    // The expected size is null because it requires the exact number of bytes to read though
843610d4a125f0144ec4915e5cef9f53e431cb117afDaichi Hirono    // MTP_OPERATION_GET_PARTIAL_OBJECT_64 allows devices to return shorter length of bytes than
844610d4a125f0144ec4915e5cef9f53e431cb117afDaichi Hirono    // requested. Destination's buffer length should be checked in |callback|.
845326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono    return readData(callback, nullptr /* expected size */, writtenSize, clientData);
8460cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood}
847a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood
8485ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::sendRequest(MtpOperationCode operation) {
8493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
850f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    mReceivedResponse = false;
8515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setOperationCode(operation);
8525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (mTransactionID > 0)
8535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mRequest.setTransactionID(mTransactionID++);
85442d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    int ret = mRequest.write(mRequestOut);
8555ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.dump();
8565ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return (ret > 0);
8575ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
8585ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
8590cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::sendData() {
8603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("sendData\n");
8615ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mData.setOperationCode(mRequest.getOperationCode());
8625ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mData.setTransactionID(mRequest.getTransactionID());
863d4b4296b401162a7a42f757c96e3652b82255b13Daichi Hirono    int ret = mData.write(mRequestOut, mPacketDivisionMode);
8645ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mData.dump();
86564c948bf5041fdfe391553315c9d028e1ee56382Tomasz Mikolajewski    return (ret >= 0);
8665ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
8675ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
8685ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::readData() {
8695ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mData.reset();
87042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    int ret = mData.read(mRequestIn1);
8713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("readData returned %d\n", ret);
8725ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret >= MTP_CONTAINER_HEADER_SIZE) {
873f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood        if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
874b8a805261bf0282e992d3608035e47d05a898710Steve Block            ALOGD("got response packet instead of data packet");
875f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood            // we got a response packet rather than data
876f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood            // copy it to mResponse
877f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood            mResponse.copyFrom(mData);
878f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood            mReceivedResponse = true;
879f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood            return false;
880f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood        }
8815ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mData.dump();
8825ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return true;
8835ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
8845ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    else {
8853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("readResponse failed\n");
8865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return false;
8875ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
8885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
8895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
8905ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpResponseCode MtpDevice::readResponse() {
8913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("readResponse\n");
892f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    if (mReceivedResponse) {
893f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood        mReceivedResponse = false;
894f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood        return mResponse.getResponseCode();
895f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    }
89642d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    int ret = mResponse.read(mRequestIn1);
8973d74457b66533b170606347e60628e55a2af255eMike Lockwood    // handle zero length packets, which might occur if the data transfer
8983d74457b66533b170606347e60628e55a2af255eMike Lockwood    // ends on a packet boundary
8993d74457b66533b170606347e60628e55a2af255eMike Lockwood    if (ret == 0)
9003d74457b66533b170606347e60628e55a2af255eMike Lockwood        ret = mResponse.read(mRequestIn1);
9015ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret >= MTP_CONTAINER_HEADER_SIZE) {
9025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mResponse.dump();
9035ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return mResponse.getResponseCode();
904f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    } else {
905b8a805261bf0282e992d3608035e47d05a898710Steve Block        ALOGD("readResponse failed\n");
9065ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return -1;
9075ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
9085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
9095ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
9108a7ffae09a019de7109b30c505561c453910bde1Daichi Hironoint MtpDevice::submitEventRequest() {
911bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    if (!mEventMutex.try_lock()) {
9128a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        // An event is being reaped on another thread.
9138a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        return -1;
9148a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    }
9158a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    if (mProcessingEvent) {
9168a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        // An event request was submitted, but no reapEventRequest called so far.
9178a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        return -1;
9188a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    }
919bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mEventMutexForInterrupt);
9208a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    mEventPacket.sendRequest(mRequestIntr);
9218a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    const int currentHandle = ++mCurrentEventHandle;
9228a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    mProcessingEvent = true;
9238a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    mEventMutex.unlock();
9248a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    return currentHandle;
9258a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono}
9268a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono
92759a90609cc340d2933c119aa47045a5c95530b48Daichi Hironoint MtpDevice::reapEventRequest(int handle, uint32_t (*parameters)[3]) {
928bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mEventMutex);
92959a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono    if (!mProcessingEvent || mCurrentEventHandle != handle || !parameters) {
9308a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        return -1;
9318a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    }
9328a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    mProcessingEvent = false;
9338a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    const int readSize = mEventPacket.readResponse(mRequestIntr->dev);
9348a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    const int result = mEventPacket.getEventCode();
93559a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono    // MTP event has three parameters.
93659a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono    (*parameters)[0] = mEventPacket.getParameter(1);
93759a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono    (*parameters)[1] = mEventPacket.getParameter(2);
93859a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono    (*parameters)[2] = mEventPacket.getParameter(3);
93959a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono    return readSize != 0 ? result : 0;
9408a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono}
9418a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono
9428a7ffae09a019de7109b30c505561c453910bde1Daichi Hironovoid MtpDevice::discardEventRequest(int handle) {
943bc1d4b41f4df1b6dd04801ea5a526d23f5321340Jerry Zhang    std::lock_guard<std::mutex> lg(mEventMutexForInterrupt);
9448a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    if (mCurrentEventHandle != handle) {
9458a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        return;
9468a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    }
9478a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    usb_request_cancel(mRequestIntr);
9488a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono}
9498a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono
9505ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}  // namespace android
951