MtpDevice.cpp revision 81ca5ade77ea518aa21fdd7434d2db5df088a115
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 39namespace android { 40 41#if 0 42static 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 53MtpDevice* 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 184MtpDevice::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 205MtpDevice::~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 215void 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 231void MtpDevice::close() { 232 if (mDevice) { 233 usb_device_release_interface(mDevice, mInterface); 234 usb_device_close(mDevice); 235 mDevice = NULL; 236 } 237} 238 239void 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 281const char* MtpDevice::getDeviceName() { 282 if (mDevice) 283 return usb_device_get_name(mDevice); 284 else 285 return "???"; 286} 287 288bool 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 309bool MtpDevice::closeSession() { 310 // FIXME 311 return true; 312} 313 314MtpDeviceInfo* 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 333MtpStorageIDList* 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 348MtpStorageInfo* 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 368MtpObjectHandleList* 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 387MtpObjectInfo* 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 409void* 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 424MtpObjectHandle 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, parent); 434 435 mData.reset(); 436 mData.putUInt32(info->mStorageID); 437 mData.putUInt16(info->mFormat); 438 mData.putUInt16(info->mProtectionStatus); 439 mData.putUInt32(info->mCompressedSize); 440 mData.putUInt16(info->mThumbFormat); 441 mData.putUInt32(info->mThumbCompressedSize); 442 mData.putUInt32(info->mThumbPixWidth); 443 mData.putUInt32(info->mThumbPixHeight); 444 mData.putUInt32(info->mImagePixWidth); 445 mData.putUInt32(info->mImagePixHeight); 446 mData.putUInt32(info->mImagePixDepth); 447 mData.putUInt32(info->mParent); 448 mData.putUInt16(info->mAssociationType); 449 mData.putUInt32(info->mAssociationDesc); 450 mData.putUInt32(info->mSequenceNumber); 451 mData.putString(info->mName); 452 453 char created[100], modified[100]; 454 formatDateTime(info->mDateCreated, created, sizeof(created)); 455 formatDateTime(info->mDateModified, modified, sizeof(modified)); 456 457 mData.putString(created); 458 mData.putString(modified); 459 if (info->mKeywords) 460 mData.putString(info->mKeywords); 461 else 462 mData.putEmptyString(); 463 464 if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) { 465 MtpResponseCode ret = readResponse(); 466 if (ret == MTP_RESPONSE_OK) { 467 info->mStorageID = mResponse.getParameter(1); 468 info->mParent = mResponse.getParameter(2); 469 info->mHandle = mResponse.getParameter(3); 470 return info->mHandle; 471 } 472 } 473 return (MtpObjectHandle)-1; 474} 475 476bool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) { 477 Mutex::Autolock autoLock(mMutex); 478 479 int remaining = info->mCompressedSize; 480 mRequest.reset(); 481 mRequest.setParameter(1, info->mHandle); 482 if (sendRequest(MTP_OPERATION_SEND_OBJECT)) { 483 // send data header 484 writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining); 485 486 char buffer[65536]; 487 while (remaining > 0) { 488 int count = read(srcFD, buffer, sizeof(buffer)); 489 if (count > 0) { 490 int written = mData.write(mRequestOut, buffer, count); 491 // FIXME check error 492 remaining -= count; 493 } else { 494 break; 495 } 496 } 497 } 498 MtpResponseCode ret = readResponse(); 499 return (remaining == 0 && ret == MTP_RESPONSE_OK); 500} 501 502bool MtpDevice::deleteObject(MtpObjectHandle handle) { 503 Mutex::Autolock autoLock(mMutex); 504 505 mRequest.reset(); 506 mRequest.setParameter(1, handle); 507 if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) { 508 MtpResponseCode ret = readResponse(); 509 if (ret == MTP_RESPONSE_OK) 510 return true; 511 } 512 return false; 513} 514 515MtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) { 516 MtpObjectInfo* info = getObjectInfo(handle); 517 if (info) { 518 MtpObjectHandle parent = info->mParent; 519 delete info; 520 return parent; 521 } else { 522 return -1; 523 } 524} 525 526MtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) { 527 MtpObjectInfo* info = getObjectInfo(handle); 528 if (info) { 529 MtpObjectHandle storageId = info->mStorageID; 530 delete info; 531 return storageId; 532 } else { 533 return -1; 534 } 535} 536 537MtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) { 538 Mutex::Autolock autoLock(mMutex); 539 540 mRequest.reset(); 541 mRequest.setParameter(1, format); 542 if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED)) 543 return NULL; 544 if (!readData()) 545 return NULL; 546 MtpResponseCode ret = readResponse(); 547 if (ret == MTP_RESPONSE_OK) { 548 return mData.getAUInt16(); 549 } 550 return NULL; 551 552} 553 554MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) { 555 Mutex::Autolock autoLock(mMutex); 556 557 mRequest.reset(); 558 mRequest.setParameter(1, code); 559 if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC)) 560 return NULL; 561 if (!readData()) 562 return NULL; 563 MtpResponseCode ret = readResponse(); 564 if (ret == MTP_RESPONSE_OK) { 565 MtpProperty* property = new MtpProperty; 566 if (property->read(mData)) 567 return property; 568 else 569 delete property; 570 } 571 return NULL; 572} 573 574MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) { 575 Mutex::Autolock autoLock(mMutex); 576 577 mRequest.reset(); 578 mRequest.setParameter(1, code); 579 mRequest.setParameter(2, format); 580 if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC)) 581 return NULL; 582 if (!readData()) 583 return NULL; 584 MtpResponseCode ret = readResponse(); 585 if (ret == MTP_RESPONSE_OK) { 586 MtpProperty* property = new MtpProperty; 587 if (property->read(mData)) 588 return property; 589 else 590 delete property; 591 } 592 return NULL; 593} 594 595bool MtpDevice::readObject(MtpObjectHandle handle, 596 bool (* callback)(void* data, int offset, int length, void* clientData), 597 size_t objectSize, void* clientData) { 598 Mutex::Autolock autoLock(mMutex); 599 bool result = false; 600 601 mRequest.reset(); 602 mRequest.setParameter(1, handle); 603 if (sendRequest(MTP_OPERATION_GET_OBJECT) 604 && mData.readDataHeader(mRequestIn1)) { 605 uint32_t length = mData.getContainerLength(); 606 if (length - MTP_CONTAINER_HEADER_SIZE != objectSize) { 607 ALOGE("readObject error objectSize: %d, length: %d", 608 objectSize, length); 609 goto fail; 610 } 611 length -= MTP_CONTAINER_HEADER_SIZE; 612 uint32_t remaining = length; 613 int offset = 0; 614 615 int initialDataLength = 0; 616 void* initialData = mData.getData(initialDataLength); 617 if (initialData) { 618 if (initialDataLength > 0) { 619 if (!callback(initialData, 0, initialDataLength, clientData)) 620 goto fail; 621 remaining -= initialDataLength; 622 offset += initialDataLength; 623 } 624 free(initialData); 625 } 626 627 // USB reads greater than 16K don't work 628 char buffer1[16384], buffer2[16384]; 629 mRequestIn1->buffer = buffer1; 630 mRequestIn2->buffer = buffer2; 631 struct usb_request* req = mRequestIn1; 632 void* writeBuffer = NULL; 633 int writeLength = 0; 634 635 while (remaining > 0 || writeBuffer) { 636 if (remaining > 0) { 637 // queue up a read request 638 req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining); 639 if (mData.readDataAsync(req)) { 640 ALOGE("readDataAsync failed"); 641 goto fail; 642 } 643 } else { 644 req = NULL; 645 } 646 647 if (writeBuffer) { 648 // write previous buffer 649 if (!callback(writeBuffer, offset, writeLength, clientData)) { 650 ALOGE("write failed"); 651 // wait for pending read before failing 652 if (req) 653 mData.readDataWait(mDevice); 654 goto fail; 655 } 656 offset += writeLength; 657 writeBuffer = NULL; 658 } 659 660 // wait for read to complete 661 if (req) { 662 int read = mData.readDataWait(mDevice); 663 if (read < 0) 664 goto fail; 665 666 if (read > 0) { 667 writeBuffer = req->buffer; 668 writeLength = read; 669 remaining -= read; 670 req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1); 671 } else { 672 writeBuffer = NULL; 673 } 674 } 675 } 676 677 MtpResponseCode response = readResponse(); 678 if (response == MTP_RESPONSE_OK) 679 result = true; 680 } 681 682fail: 683 return result; 684} 685 686// reads the object's data and writes it to the specified file path 687bool 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 bool result = readObject(handle, fd); 702 ::close(fd); 703 return result; 704} 705 706bool MtpDevice::readObject(MtpObjectHandle handle, int fd) { 707 ALOGD("readObject: %d", fd); 708 709 Mutex::Autolock autoLock(mMutex); 710 711 mRequest.reset(); 712 mRequest.setParameter(1, handle); 713 if (sendRequest(MTP_OPERATION_GET_OBJECT) && mData.readDataHeader(mRequestIn1)) { 714 uint32_t length = mData.getContainerLength(); 715 if (length < MTP_CONTAINER_HEADER_SIZE) { 716 ALOGE("Invalid container length."); 717 return false; 718 } 719 length -= MTP_CONTAINER_HEADER_SIZE; 720 uint32_t remaining = length; 721 722 bool writingError = false; 723 int initialDataLength = 0; 724 void* initialData = mData.getData(initialDataLength); 725 if (initialData) { 726 if (initialDataLength > 0) { 727 if (write(fd, initialData, initialDataLength) != initialDataLength) { 728 ALOGE("Failed to write initial data."); 729 writingError = true; 730 } 731 remaining -= initialDataLength; 732 } 733 free(initialData); 734 } 735 736 // USB reads greater than 16K don't work 737 char buffer1[16384], buffer2[16384]; 738 mRequestIn1->buffer = buffer1; 739 mRequestIn2->buffer = buffer2; 740 struct usb_request* req = mRequestIn1; 741 void* writeBuffer = NULL; 742 int writeLength = 0; 743 744 while (remaining > 0 || writeBuffer) { 745 if (remaining > 0) { 746 // queue up a read request 747 req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining); 748 if (mData.readDataAsync(req)) { 749 ALOGE("readDataAsync failed"); 750 return false; 751 } 752 } else { 753 req = NULL; 754 } 755 756 if (writeBuffer && !writingError) { 757 // write previous buffer 758 if (write(fd, writeBuffer, writeLength) != writeLength) { 759 writingError = true; 760 } 761 } 762 writeBuffer = NULL; 763 764 // wait for read to complete 765 if (req) { 766 int read = mData.readDataWait(mDevice); 767 if (read < 0) { 768 ALOGE("readDataWait failed."); 769 return false; 770 } 771 772 if (read > 0) { 773 writeBuffer = req->buffer; 774 writeLength = read; 775 remaining -= read; 776 req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1); 777 } else { 778 writeBuffer = NULL; 779 } 780 } 781 } 782 783 MtpResponseCode response = readResponse(); 784 return response == MTP_RESPONSE_OK && !writingError; 785 } 786 787 return false; 788} 789 790bool MtpDevice::sendRequest(MtpOperationCode operation) { 791 ALOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation)); 792 mReceivedResponse = false; 793 mRequest.setOperationCode(operation); 794 if (mTransactionID > 0) 795 mRequest.setTransactionID(mTransactionID++); 796 int ret = mRequest.write(mRequestOut); 797 mRequest.dump(); 798 return (ret > 0); 799} 800 801bool MtpDevice::sendData() { 802 ALOGV("sendData\n"); 803 mData.setOperationCode(mRequest.getOperationCode()); 804 mData.setTransactionID(mRequest.getTransactionID()); 805 int ret = mData.write(mRequestOut); 806 mData.dump(); 807 return (ret >= 0); 808} 809 810bool MtpDevice::readData() { 811 mData.reset(); 812 int ret = mData.read(mRequestIn1); 813 ALOGV("readData returned %d\n", ret); 814 if (ret >= MTP_CONTAINER_HEADER_SIZE) { 815 if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) { 816 ALOGD("got response packet instead of data packet"); 817 // we got a response packet rather than data 818 // copy it to mResponse 819 mResponse.copyFrom(mData); 820 mReceivedResponse = true; 821 return false; 822 } 823 mData.dump(); 824 return true; 825 } 826 else { 827 ALOGV("readResponse failed\n"); 828 return false; 829 } 830} 831 832bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) { 833 mData.setOperationCode(operation); 834 mData.setTransactionID(mRequest.getTransactionID()); 835 return (!mData.writeDataHeader(mRequestOut, dataLength)); 836} 837 838MtpResponseCode MtpDevice::readResponse() { 839 ALOGV("readResponse\n"); 840 if (mReceivedResponse) { 841 mReceivedResponse = false; 842 return mResponse.getResponseCode(); 843 } 844 int ret = mResponse.read(mRequestIn1); 845 // handle zero length packets, which might occur if the data transfer 846 // ends on a packet boundary 847 if (ret == 0) 848 ret = mResponse.read(mRequestIn1); 849 if (ret >= MTP_CONTAINER_HEADER_SIZE) { 850 mResponse.dump(); 851 return mResponse.getResponseCode(); 852 } else { 853 ALOGD("readResponse failed\n"); 854 return -1; 855 } 856} 857 858} // namespace android 859