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