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