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