MtpDevice.cpp revision d6dabe95eb59c3d95f94825d08a6028bab06cbdc
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
42d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#if 0
4323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodstatic bool isMtpDevice(uint16_t vendor, uint16_t product) {
4423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    // Sandisk Sansa Fuze
4523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    if (vendor == 0x0781 && product == 0x74c2)
4623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood        return true;
4723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    // Samsung YP-Z5
4823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    if (vendor == 0x04e8 && product == 0x503c)
4923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood        return true;
5023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    return false;
5123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood}
52d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#endif
5323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
544fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirononamespace {
554fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
564fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hironobool writeToFd(void* data, int /* unused_offset */, int length, void* clientData) {
574fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    const int fd = *static_cast<int*>(clientData);
584fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    return write(fd, data, length) == length;
594fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono}
604fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
614fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono}
624fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
6323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike LockwoodMtpDevice* MtpDevice::open(const char* deviceName, int fd) {
6423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    struct usb_device *device = usb_device_new(deviceName, fd);
6523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    if (!device) {
6629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("usb_device_new failed for %s", deviceName);
6723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood        return NULL;
6823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    }
6923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
7023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    struct usb_descriptor_header* desc;
7123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    struct usb_descriptor_iter iter;
7223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
7323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    usb_descriptor_iter_init(device, &iter);
7423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
7523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {
7623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood        if (desc->bDescriptorType == USB_DT_INTERFACE) {
7723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;
7823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
7923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            if (interface->bInterfaceClass == USB_CLASS_STILL_IMAGE &&
8023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                interface->bInterfaceSubClass == 1 && // Still Image Capture
8123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                interface->bInterfaceProtocol == 1)     // Picture Transfer Protocol (PIMA 15470)
8223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            {
8331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                char* manufacturerName = usb_device_get_manufacturer_name(device);
8431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                char* productName = usb_device_get_product_name(device);
85b8a805261bf0282e992d3608035e47d05a898710Steve Block                ALOGD("Found camera: \"%s\" \"%s\"\n", manufacturerName, productName);
8631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                free(manufacturerName);
8731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                free(productName);
8823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            } else if (interface->bInterfaceClass == 0xFF &&
8923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    interface->bInterfaceSubClass == 0xFF &&
9023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    interface->bInterfaceProtocol == 0) {
9123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                char* interfaceName = usb_device_get_string(device, interface->iInterface);
9231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                if (!interfaceName) {
9323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    continue;
9431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                } else if (strcmp(interfaceName, "MTP")) {
9531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    free(interfaceName);
9631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    continue;
9731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                }
9831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                free(interfaceName);
9931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root
10023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                // Looks like an android style MTP device
10131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                char* manufacturerName = usb_device_get_manufacturer_name(device);
10231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                char* productName = usb_device_get_product_name(device);
103b8a805261bf0282e992d3608035e47d05a898710Steve Block                ALOGD("Found MTP device: \"%s\" \"%s\"\n", manufacturerName, productName);
10431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                free(manufacturerName);
10531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                free(productName);
106d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood            }
107d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#if 0
108d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood             else {
10923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                // look for special cased devices based on vendor/product ID
11023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                // we are doing this mainly for testing purposes
11123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                uint16_t vendor = usb_device_get_vendor_id(device);
11223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                uint16_t product = usb_device_get_product_id(device);
11323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                if (!isMtpDevice(vendor, product)) {
11423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    // not an MTP or PTP device
11523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    continue;
11623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                }
11723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                // request MTP OS string and descriptor
11823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                // some music players need to see this before entering MTP mode.
11923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                char buffer[256];
12023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                memset(buffer, 0, sizeof(buffer));
121f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood                int ret = usb_device_control_transfer(device,
12223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                        USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_STANDARD,
12323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                        USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | 0xEE,
124f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood                        0, buffer, sizeof(buffer), 0);
125f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood                printf("usb_device_control_transfer returned %d errno: %d\n", ret, errno);
12623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                if (ret > 0) {
12723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    printf("got MTP string %s\n", buffer);
128f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood                    ret = usb_device_control_transfer(device,
12923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                            USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, 1,
130f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood                            0, 4, buffer, sizeof(buffer), 0);
13123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    printf("OS descriptor got %d\n", ret);
13223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                } else {
13323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    printf("no MTP string\n");
13423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                }
13523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            }
136d6dabe95eb59c3d95f94825d08a6028bab06cbdcDaichi Hirono#else
137d6dabe95eb59c3d95f94825d08a6028bab06cbdcDaichi Hirono            else {
138d6dabe95eb59c3d95f94825d08a6028bab06cbdcDaichi Hirono                continue;
139d6dabe95eb59c3d95f94825d08a6028bab06cbdcDaichi Hirono            }
140d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#endif
14123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            // if we got here, then we have a likely MTP or PTP device
14223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
14323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            // interface should be followed by three endpoints
14423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            struct usb_endpoint_descriptor *ep;
14523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            struct usb_endpoint_descriptor *ep_in_desc = NULL;
14623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            struct usb_endpoint_descriptor *ep_out_desc = NULL;
14723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            struct usb_endpoint_descriptor *ep_intr_desc = NULL;
1488023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang            //USB3 add USB_DT_SS_ENDPOINT_COMP as companion descriptor;
1498023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang            struct usb_ss_ep_comp_descriptor *ep_ss_ep_comp_desc = NULL;
15023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            for (int i = 0; i < 3; i++) {
15123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
1528023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang                if (ep && ep->bDescriptorType == USB_DT_SS_ENDPOINT_COMP) {
1538023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang                    ALOGD("Descriptor type is USB_DT_SS_ENDPOINT_COMP for USB3 \n");
1548023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang                    ep_ss_ep_comp_desc = (usb_ss_ep_comp_descriptor*)ep;
1558023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang                    ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
1568023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang                 }
1578023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang
15823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) {
15929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("endpoints not found\n");
16031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    usb_device_close(device);
16123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    return NULL;
16223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                }
1638023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang
16423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
16523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
16623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                        ep_in_desc = ep;
16723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    else
16823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                        ep_out_desc = ep;
16923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                } else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT &&
17023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
17123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                    ep_intr_desc = ep;
17223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                }
17323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            }
17423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) {
17529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("endpoints not found\n");
17631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                usb_device_close(device);
17723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                return NULL;
17823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            }
17923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
18023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            if (usb_device_claim_interface(device, interface->bInterfaceNumber)) {
18129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("usb_device_claim_interface failed errno: %d\n", errno);
18231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                usb_device_close(device);
18323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                return NULL;
18423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            }
18523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
18623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber,
18723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood                        ep_in_desc, ep_out_desc, ep_intr_desc);
18823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            mtpDevice->initialize();
18923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood            return mtpDevice;
19023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood        }
19123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    }
19223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
19323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    usb_device_close(device);
19429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block    ALOGE("device not found");
19523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood    return NULL;
19623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood}
19723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
1985ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDevice::MtpDevice(struct usb_device* device, int interface,
19942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood            const struct usb_endpoint_descriptor *ep_in,
20042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood            const struct usb_endpoint_descriptor *ep_out,
20142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood            const struct usb_endpoint_descriptor *ep_intr)
2025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    :   mDevice(device),
2035ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mInterface(interface),
20442d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood        mRequestIn1(NULL),
20542d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood        mRequestIn2(NULL),
20642d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood        mRequestOut(NULL),
20742d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood        mRequestIntr(NULL),
2085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mDeviceInfo(NULL),
2095ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mSessionID(0),
210f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood        mTransactionID(0),
2118a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        mReceivedResponse(false),
2128a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        mProcessingEvent(false),
2138a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        mCurrentEventHandle(0)
2145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood{
21542d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    mRequestIn1 = usb_request_new(device, ep_in);
21642d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    mRequestIn2 = usb_request_new(device, ep_in);
21742d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    mRequestOut = usb_request_new(device, ep_out);
21842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    mRequestIntr = usb_request_new(device, ep_intr);
2195ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
2205ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
2215ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDevice::~MtpDevice() {
2225ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    close();
2233ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn    for (size_t i = 0; i < mDeviceProperties.size(); i++)
224a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        delete mDeviceProperties[i];
22542d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    usb_request_free(mRequestIn1);
22642d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    usb_request_free(mRequestIn2);
22742d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    usb_request_free(mRequestOut);
22842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    usb_request_free(mRequestIntr);
2295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
2305ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
2315ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid MtpDevice::initialize() {
2325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    openSession();
2335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mDeviceInfo = getDeviceInfo();
2345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (mDeviceInfo) {
235a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        if (mDeviceInfo->mDeviceProperties) {
236a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood            int count = mDeviceInfo->mDeviceProperties->size();
237a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood            for (int i = 0; i < count; i++) {
238a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
239a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                MtpProperty* property = getDevicePropDesc(propCode);
2400c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                if (property)
241a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                    mDeviceProperties.push(property);
242a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood            }
243a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        }
2445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
2455ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
2465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
2475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid MtpDevice::close() {
2485ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (mDevice) {
2495ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        usb_device_release_interface(mDevice, mInterface);
2505ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        usb_device_close(mDevice);
2515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mDevice = NULL;
2525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
2535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
2545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
2550c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwoodvoid MtpDevice::print() {
2560c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood    if (mDeviceInfo) {
2570c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood        mDeviceInfo->print();
2580c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood
2590c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood        if (mDeviceInfo->mDeviceProperties) {
260df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("***** DEVICE PROPERTIES *****\n");
2610c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood            int count = mDeviceInfo->mDeviceProperties->size();
2620c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood            for (int i = 0; i < count; i++) {
2630c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
2640c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                MtpProperty* property = getDevicePropDesc(propCode);
2650c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                if (property) {
2660c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                    property->print();
26731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    delete property;
2680c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                }
2690c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood            }
2700c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood        }
2710c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood    }
2720c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood
2730c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood    if (mDeviceInfo->mPlaybackFormats) {
274df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("***** OBJECT PROPERTIES *****\n");
2750c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood        int count = mDeviceInfo->mPlaybackFormats->size();
2760c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood        for (int i = 0; i < count; i++) {
2770c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood            MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i];
278df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format));
2790c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood            MtpObjectPropertyList* props = getObjectPropsSupported(format);
2800c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood            if (props) {
2813ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn                for (size_t j = 0; j < props->size(); j++) {
2820c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                    MtpObjectProperty prop = (*props)[j];
28399e393a39a31bfbdeb435462939519e2d0279433Mike Lockwood                    MtpProperty* property = getObjectPropDesc(prop, format);
28431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    if (property) {
2850c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                        property->print();
28631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                        delete property;
28731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    } else {
28829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                        ALOGE("could not fetch property: %s",
2890c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                                MtpDebug::getObjectPropCodeName(prop));
29031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                    }
2910c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood                }
2920c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood            }
2930c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood        }
2940c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood    }
2950c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood}
2960c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood
2975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodconst char* MtpDevice::getDeviceName() {
2985ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (mDevice)
2995ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return usb_device_get_name(mDevice);
3005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    else
3015ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return "???";
3025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
3035ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3045ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::openSession() {
3050cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
3060cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3075ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mSessionID = 0;
3085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mTransactionID = 0;
3095ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpSessionID newSession = 1;
3105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
3115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(1, newSession);
3125ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_OPEN_SESSION))
3135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return false;
3145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
3155ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN)
3165ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        newSession = mResponse.getParameter(1);
3175ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    else if (ret != MTP_RESPONSE_OK)
3185ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return false;
3195ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3205ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mSessionID = newSession;
3215ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mTransactionID = 1;
3225ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return true;
3235ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
3245ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3255ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::closeSession() {
3265ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    // FIXME
3275ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return true;
3285ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
3295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3305ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDeviceInfo* MtpDevice::getDeviceInfo() {
3310cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
3320cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
3345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO))
3355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
3375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
3395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
3405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        MtpDeviceInfo* info = new MtpDeviceInfo;
341ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        if (info->read(mData))
342ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            return info;
343ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        else
344ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            delete info;
3455ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
3465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
3475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
3485ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3495ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageIDList* MtpDevice::getStorageIDs() {
3500cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
3510cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
3535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS))
3545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3555ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
3565ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3575ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
3585ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
3595ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return mData.getAUInt32();
3605ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
3615ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
3625ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
3635ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3645ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
3650cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
3660cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3675ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
3685ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(1, storageID);
3695ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO))
3705ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3715ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
3725ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3735ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
3745ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
3755ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        MtpStorageInfo* info = new MtpStorageInfo(storageID);
376ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        if (info->read(mData))
377ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            return info;
378ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        else
379ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            delete info;
3805ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
3815ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
3825ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
3835ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
3845ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
3855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood            MtpObjectFormat format, MtpObjectHandle parent) {
3860cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
3870cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
3895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(1, storageID);
3905ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(2, format);
3915ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(3, parent);
3925ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES))
3935ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
3955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
3965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
3975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
3985ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return mData.getAUInt32();
3995ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
4005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
4015ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
4025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
4035ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
4040cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
4050cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4066afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    // FIXME - we might want to add some caching here
4076afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood
4085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
4095ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(1, handle);
4105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO))
4115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
4125ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
4135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
4145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
4155ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
4165ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        MtpObjectInfo* info = new MtpObjectInfo(handle);
417ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        if (info->read(mData))
418ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            return info;
419ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        else
420ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            delete info;
4215ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
4225ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
4235ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
4245ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
4253e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwoodvoid* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) {
4260cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
4270cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4283e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    mRequest.reset();
4293e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    mRequest.setParameter(1, handle);
4303e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
4313e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood        MtpResponseCode ret = readResponse();
4323e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood        if (ret == MTP_RESPONSE_OK) {
4334fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            return mData.getData(&outLength);
4343e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood        }
4353e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    }
4363e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    outLength = 0;
4373e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    return NULL;
4386afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood}
4396afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood
4400cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike LockwoodMtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) {
4410cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
4420cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4430cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mRequest.reset();
4440cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    MtpObjectHandle parent = info->mParent;
4450cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    if (parent == 0)
4460cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        parent = MTP_PARENT_ROOT;
4470cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4480cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mRequest.setParameter(1, info->mStorageID);
44964c948bf5041fdfe391553315c9d028e1ee56382Tomasz Mikolajewski    mRequest.setParameter(2, parent);
4500cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
45164c948bf5041fdfe391553315c9d028e1ee56382Tomasz Mikolajewski    mData.reset();
4520cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mStorageID);
4530cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt16(info->mFormat);
4540cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt16(info->mProtectionStatus);
4550cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mCompressedSize);
4560cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt16(info->mThumbFormat);
4570cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mThumbCompressedSize);
4580cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mThumbPixWidth);
4590cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mThumbPixHeight);
4600cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mImagePixWidth);
4610cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mImagePixHeight);
4620cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mImagePixDepth);
4630cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mParent);
4640cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt16(info->mAssociationType);
4650cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mAssociationDesc);
4660cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mSequenceNumber);
4670cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putString(info->mName);
4680cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4690cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    char created[100], modified[100];
4700cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    formatDateTime(info->mDateCreated, created, sizeof(created));
4710cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    formatDateTime(info->mDateModified, modified, sizeof(modified));
4720cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4730cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putString(created);
4740cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putString(modified);
4750cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    if (info->mKeywords)
4760cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        mData.putString(info->mKeywords);
4770cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    else
4780cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        mData.putEmptyString();
4790cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4800cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood   if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
4810cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        MtpResponseCode ret = readResponse();
4820cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        if (ret == MTP_RESPONSE_OK) {
4830cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            info->mStorageID = mResponse.getParameter(1);
4840cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            info->mParent = mResponse.getParameter(2);
4850cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            info->mHandle = mResponse.getParameter(3);
4860cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            return info->mHandle;
4870cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        }
4880cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
4890cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    return (MtpObjectHandle)-1;
4900cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood}
4910cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
492532b4f23c7e08fdae9fff189c4b565f6216ffd2aTomasz Mikolajewskibool MtpDevice::sendObject(MtpObjectHandle handle, int size, int srcFD) {
4930cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
4940cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
495532b4f23c7e08fdae9fff189c4b565f6216ffd2aTomasz Mikolajewski    int remaining = size;
4960cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mRequest.reset();
497532b4f23c7e08fdae9fff189c4b565f6216ffd2aTomasz Mikolajewski    mRequest.setParameter(1, handle);
4980cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
4990cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        // send data header
5000cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
5010cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
502532b4f23c7e08fdae9fff189c4b565f6216ffd2aTomasz Mikolajewski        // USB writes greater than 16K don't work
503532b4f23c7e08fdae9fff189c4b565f6216ffd2aTomasz Mikolajewski        char buffer[MTP_BUFFER_SIZE];
5040cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        while (remaining > 0) {
5050cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            int count = read(srcFD, buffer, sizeof(buffer));
5060cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            if (count > 0) {
50742d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood                int written = mData.write(mRequestOut, buffer, count);
5080cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                // FIXME check error
5090cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                remaining -= count;
5100cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            } else {
5110cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                break;
5120cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            }
5130cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        }
5140cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
5150cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    MtpResponseCode ret = readResponse();
5160cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    return (remaining == 0 && ret == MTP_RESPONSE_OK);
5170cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood}
5180cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
5196afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwoodbool MtpDevice::deleteObject(MtpObjectHandle handle) {
5200cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
5210cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
5226afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    mRequest.reset();
5236afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    mRequest.setParameter(1, handle);
5246afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) {
5256afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        MtpResponseCode ret = readResponse();
5266afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        if (ret == MTP_RESPONSE_OK)
5276afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood            return true;
5286afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    }
5296afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    return false;
5306afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood}
5316afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood
5326afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) {
5336afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    MtpObjectInfo* info = getObjectInfo(handle);
53431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root    if (info) {
53531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root        MtpObjectHandle parent = info->mParent;
53631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root        delete info;
53731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root        return parent;
53831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root    } else {
5396afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        return -1;
54031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root    }
5416afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood}
5423e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood
5436afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) {
5446afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    MtpObjectInfo* info = getObjectInfo(handle);
54531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root    if (info) {
54631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root        MtpObjectHandle storageId = info->mStorageID;
54731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root        delete info;
54831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root        return storageId;
54931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root    } else {
5506afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        return -1;
55131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root    }
5523e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood}
5533e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood
55498693f674125484de8873d969c209276a6dd604bMike LockwoodMtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) {
55598693f674125484de8873d969c209276a6dd604bMike Lockwood    Mutex::Autolock autoLock(mMutex);
55698693f674125484de8873d969c209276a6dd604bMike Lockwood
55798693f674125484de8873d969c209276a6dd604bMike Lockwood    mRequest.reset();
55898693f674125484de8873d969c209276a6dd604bMike Lockwood    mRequest.setParameter(1, format);
55998693f674125484de8873d969c209276a6dd604bMike Lockwood    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED))
56098693f674125484de8873d969c209276a6dd604bMike Lockwood        return NULL;
56198693f674125484de8873d969c209276a6dd604bMike Lockwood    if (!readData())
56298693f674125484de8873d969c209276a6dd604bMike Lockwood        return NULL;
56398693f674125484de8873d969c209276a6dd604bMike Lockwood    MtpResponseCode ret = readResponse();
56498693f674125484de8873d969c209276a6dd604bMike Lockwood    if (ret == MTP_RESPONSE_OK) {
56598693f674125484de8873d969c209276a6dd604bMike Lockwood        return mData.getAUInt16();
56698693f674125484de8873d969c209276a6dd604bMike Lockwood    }
56798693f674125484de8873d969c209276a6dd604bMike Lockwood    return NULL;
56898693f674125484de8873d969c209276a6dd604bMike Lockwood
56998693f674125484de8873d969c209276a6dd604bMike Lockwood}
57098693f674125484de8873d969c209276a6dd604bMike Lockwood
571a6c490b8b2d96ebaab632286029463f932ae3b6bMike LockwoodMtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
5720cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
5730cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
574a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    mRequest.reset();
575a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    mRequest.setParameter(1, code);
576a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC))
577a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        return NULL;
578a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    if (!readData())
579a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        return NULL;
580a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    MtpResponseCode ret = readResponse();
581a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    if (ret == MTP_RESPONSE_OK) {
582a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        MtpProperty* property = new MtpProperty;
583ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        if (property->read(mData))
584ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            return property;
585ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        else
586ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            delete property;
587a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    }
588a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    return NULL;
589a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood}
590a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood
59199e393a39a31bfbdeb435462939519e2d0279433Mike LockwoodMtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) {
59298693f674125484de8873d969c209276a6dd604bMike Lockwood    Mutex::Autolock autoLock(mMutex);
59398693f674125484de8873d969c209276a6dd604bMike Lockwood
59498693f674125484de8873d969c209276a6dd604bMike Lockwood    mRequest.reset();
59598693f674125484de8873d969c209276a6dd604bMike Lockwood    mRequest.setParameter(1, code);
59699e393a39a31bfbdeb435462939519e2d0279433Mike Lockwood    mRequest.setParameter(2, format);
59798693f674125484de8873d969c209276a6dd604bMike Lockwood    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC))
59898693f674125484de8873d969c209276a6dd604bMike Lockwood        return NULL;
59998693f674125484de8873d969c209276a6dd604bMike Lockwood    if (!readData())
60098693f674125484de8873d969c209276a6dd604bMike Lockwood        return NULL;
60198693f674125484de8873d969c209276a6dd604bMike Lockwood    MtpResponseCode ret = readResponse();
60298693f674125484de8873d969c209276a6dd604bMike Lockwood    if (ret == MTP_RESPONSE_OK) {
60398693f674125484de8873d969c209276a6dd604bMike Lockwood        MtpProperty* property = new MtpProperty;
604ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        if (property->read(mData))
605ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            return property;
606ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood        else
607ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood            delete property;
60898693f674125484de8873d969c209276a6dd604bMike Lockwood    }
60998693f674125484de8873d969c209276a6dd604bMike Lockwood    return NULL;
61098693f674125484de8873d969c209276a6dd604bMike Lockwood}
61198693f674125484de8873d969c209276a6dd604bMike Lockwood
61223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodbool MtpDevice::readObject(MtpObjectHandle handle,
6134fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                           ReadObjectCallback callback,
6144fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                           size_t expectedLength,
6154fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                           void* clientData) {
6164fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    return readObjectInternal(handle, callback, &expectedLength, clientData);
61723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood}
61823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood
619b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood// reads the object's data and writes it to the specified file path
62027afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwoodbool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
621b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("readObject: %s", destPath);
622af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich    int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
623b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood    if (fd < 0) {
62429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("open failed for %s", destPath);
625b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood        return false;
6260cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
6270cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
62827afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood    fchown(fd, getuid(), group);
62927afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood    // set permissions
63027afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood    int mask = umask(0);
63127afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood    fchmod(fd, perm);
63227afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood    umask(mask);
63327afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood
634025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski    bool result = readObject(handle, fd);
635025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski    ::close(fd);
636025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski    return result;
637025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski}
638025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski
639025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewskibool MtpDevice::readObject(MtpObjectHandle handle, int fd) {
640025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski    ALOGD("readObject: %d", fd);
6414fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    return readObjectInternal(handle, writeToFd, NULL /* expected size */, &fd);
6424fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono}
643025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski
6444fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hironobool MtpDevice::readObjectInternal(MtpObjectHandle handle,
6454fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                                   ReadObjectCallback callback,
6464fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                                   const size_t* expectedLength,
6474fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                                   void* clientData) {
648b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood    Mutex::Autolock autoLock(mMutex);
6490cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
650b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood    mRequest.reset();
651b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood    mRequest.setParameter(1, handle);
6524fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    if (!sendRequest(MTP_OPERATION_GET_OBJECT)) {
6534fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        ALOGE("Failed to send a read request.");
6544fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        return false;
6554fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    }
6564fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
6574fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    if (!mData.readDataHeader(mRequestIn1)) {
6584fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        ALOGE("Failed to read header.");
6594fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        return false;
6604fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    }
6614fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
6624fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    const uint32_t fullLength = mData.getContainerLength();
6634fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    if ((!expectedLength && fullLength < MTP_CONTAINER_HEADER_SIZE) ||
6644fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        (expectedLength && *expectedLength + MTP_CONTAINER_HEADER_SIZE != fullLength)) {
6654fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        ALOGE("readObject error length: %d", fullLength);
6664fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        return false;
6674fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    }
6684fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
6694fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    const uint32_t length = fullLength - MTP_CONTAINER_HEADER_SIZE;
6704fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    uint32_t offset = 0;
6714fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    bool writingError = false;
672b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood
6734fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    {
674b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood        int initialDataLength = 0;
6754fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        void* const initialData = mData.getData(&initialDataLength);
676b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood        if (initialData) {
677b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood            if (initialDataLength > 0) {
6784fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                if (!callback(initialData, offset, initialDataLength, clientData)) {
67981ca5ade77ea518aa21fdd7434d2db5df088a115Daichi Hirono                    ALOGE("Failed to write initial data.");
68081ca5ade77ea518aa21fdd7434d2db5df088a115Daichi Hirono                    writingError = true;
68131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root                }
6824fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                offset += initialDataLength;
6830cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            }
684b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood            free(initialData);
6850cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        }
6864fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    }
6870cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
6884fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    // USB reads greater than 16K don't work.
6894fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    char buffer1[MTP_BUFFER_SIZE], buffer2[MTP_BUFFER_SIZE];
6904fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    mRequestIn1->buffer = buffer1;
6914fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    mRequestIn2->buffer = buffer2;
6924fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    struct usb_request* req = NULL;
6934fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono
6944fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    while (offset < length) {
6954fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        // Wait for previous read to complete.
69642d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood        void* writeBuffer = NULL;
697b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood        int writeLength = 0;
6984fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        if (req) {
6994fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            const int read = mData.readDataWait(mDevice);
7004fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            if (read < 0) {
7014fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                ALOGE("readDataWait failed.");
7024fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                return false;
7030cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            }
7044fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            writeBuffer = req->buffer;
7054fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            writeLength = read;
7064fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        }
7070cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
7084fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        // Request to read next chunk.
7094fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        const uint32_t nextOffset = offset + writeLength;
7104fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        if (nextOffset < length) {
7114fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            // Queue up a read request.
7124fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            const size_t remaining = length - nextOffset;
7134fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
7144fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            req->buffer_length =
7154fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                    remaining > MTP_BUFFER_SIZE ? static_cast<size_t>(MTP_BUFFER_SIZE) : remaining;
7164fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            if (mData.readDataAsync(req) != 0) {
7174fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                ALOGE("readDataAsync failed");
7184fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                return false;
719b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood            }
7204fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        }
7210cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
7224fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        // Write previous buffer.
7234fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        if (writeBuffer && !writingError) {
7244fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono            if (!callback(writeBuffer, offset, writeLength, clientData)) {
7254fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                ALOGE("write failed");
7264fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono                writingError = true;
727b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood            }
728b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood        }
7294fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono        offset = nextOffset;
7300cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
731b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood
7324fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono    return readResponse() == MTP_RESPONSE_OK && !writingError;
7330cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood}
734a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood
7355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::sendRequest(MtpOperationCode operation) {
7363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
737f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    mReceivedResponse = false;
7385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setOperationCode(operation);
7395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (mTransactionID > 0)
7405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mRequest.setTransactionID(mTransactionID++);
74142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    int ret = mRequest.write(mRequestOut);
7425ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.dump();
7435ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return (ret > 0);
7445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
7455ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
7460cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::sendData() {
7473856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("sendData\n");
7485ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mData.setOperationCode(mRequest.getOperationCode());
7495ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mData.setTransactionID(mRequest.getTransactionID());
75042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    int ret = mData.write(mRequestOut);
7515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mData.dump();
75264c948bf5041fdfe391553315c9d028e1ee56382Tomasz Mikolajewski    return (ret >= 0);
7535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
7545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
7555ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::readData() {
7565ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mData.reset();
75742d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    int ret = mData.read(mRequestIn1);
7583856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("readData returned %d\n", ret);
7595ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret >= MTP_CONTAINER_HEADER_SIZE) {
760f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood        if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
761b8a805261bf0282e992d3608035e47d05a898710Steve Block            ALOGD("got response packet instead of data packet");
762f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood            // we got a response packet rather than data
763f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood            // copy it to mResponse
764f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood            mResponse.copyFrom(mData);
765f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood            mReceivedResponse = true;
766f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood            return false;
767f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood        }
7685ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mData.dump();
7695ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return true;
7705ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
7715ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    else {
7723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("readResponse failed\n");
7735ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return false;
7745ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
7755ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
7765ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
7770cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
7780cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.setOperationCode(operation);
7790cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.setTransactionID(mRequest.getTransactionID());
78042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    return (!mData.writeDataHeader(mRequestOut, dataLength));
7810cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood}
7820cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
7835ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpResponseCode MtpDevice::readResponse() {
7843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("readResponse\n");
785f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    if (mReceivedResponse) {
786f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood        mReceivedResponse = false;
787f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood        return mResponse.getResponseCode();
788f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    }
78942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood    int ret = mResponse.read(mRequestIn1);
7903d74457b66533b170606347e60628e55a2af255eMike Lockwood    // handle zero length packets, which might occur if the data transfer
7913d74457b66533b170606347e60628e55a2af255eMike Lockwood    // ends on a packet boundary
7923d74457b66533b170606347e60628e55a2af255eMike Lockwood    if (ret == 0)
7933d74457b66533b170606347e60628e55a2af255eMike Lockwood        ret = mResponse.read(mRequestIn1);
7945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret >= MTP_CONTAINER_HEADER_SIZE) {
7955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mResponse.dump();
7965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return mResponse.getResponseCode();
797f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    } else {
798b8a805261bf0282e992d3608035e47d05a898710Steve Block        ALOGD("readResponse failed\n");
7995ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return -1;
8005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
8015ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
8025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
8038a7ffae09a019de7109b30c505561c453910bde1Daichi Hironoint MtpDevice::submitEventRequest() {
8048a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    if (mEventMutex.tryLock()) {
8058a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        // An event is being reaped on another thread.
8068a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        return -1;
8078a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    }
8088a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    if (mProcessingEvent) {
8098a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        // An event request was submitted, but no reapEventRequest called so far.
8108a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        return -1;
8118a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    }
8128a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    Mutex::Autolock autoLock(mEventMutexForInterrupt);
8138a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    mEventPacket.sendRequest(mRequestIntr);
8148a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    const int currentHandle = ++mCurrentEventHandle;
8158a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    mProcessingEvent = true;
8168a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    mEventMutex.unlock();
8178a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    return currentHandle;
8188a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono}
8198a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono
8208a7ffae09a019de7109b30c505561c453910bde1Daichi Hironoint MtpDevice::reapEventRequest(int handle) {
8218a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    Mutex::Autolock autoLock(mEventMutex);
8228a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    if (!mProcessingEvent || mCurrentEventHandle != handle) {
8238a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        return -1;
8248a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    }
8258a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    mProcessingEvent = false;
8268a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    const int readSize = mEventPacket.readResponse(mRequestIntr->dev);
8278a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    const int result = mEventPacket.getEventCode();
8288a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    return readSize == 0 ? 0 : result;
8298a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono}
8308a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono
8318a7ffae09a019de7109b30c505561c453910bde1Daichi Hironovoid MtpDevice::discardEventRequest(int handle) {
8328a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    Mutex::Autolock autoLock(mEventMutexForInterrupt);
8338a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    if (mCurrentEventHandle != handle) {
8348a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono        return;
8358a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    }
8368a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono    usb_request_cancel(mRequestIntr);
8378a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono}
8388a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono
8395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}  // namespace android
840