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