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