MtpDevice.cpp revision 33d58162896868f387416289c8b33266be0a3360
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 int ret = usb_device_claim_interface(device, interface->bInterfaceNumber); 185 if (ret && errno == EBUSY) { 186 // disconnect kernel driver and try again 187 usb_device_connect_kernel_driver(device, interface->bInterfaceNumber, false); 188 ret = usb_device_claim_interface(device, interface->bInterfaceNumber); 189 } 190 if (ret) { 191 ALOGE("usb_device_claim_interface failed errno: %d\n", errno); 192 usb_device_close(device); 193 return NULL; 194 } 195 196 MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber, 197 ep_in_desc, ep_out_desc, ep_intr_desc); 198 mtpDevice->initialize(); 199 return mtpDevice; 200 } 201 } 202 203 usb_device_close(device); 204 ALOGE("device not found"); 205 return NULL; 206} 207 208MtpDevice::MtpDevice(struct usb_device* device, int interface, 209 const struct usb_endpoint_descriptor *ep_in, 210 const struct usb_endpoint_descriptor *ep_out, 211 const struct usb_endpoint_descriptor *ep_intr) 212 : mDevice(device), 213 mInterface(interface), 214 mRequestIn1(NULL), 215 mRequestIn2(NULL), 216 mRequestOut(NULL), 217 mRequestIntr(NULL), 218 mDeviceInfo(NULL), 219 mSessionID(0), 220 mTransactionID(0), 221 mReceivedResponse(false), 222 mProcessingEvent(false), 223 mCurrentEventHandle(0) 224{ 225 mRequestIn1 = usb_request_new(device, ep_in); 226 mRequestIn2 = usb_request_new(device, ep_in); 227 mRequestOut = usb_request_new(device, ep_out); 228 mRequestIntr = usb_request_new(device, ep_intr); 229} 230 231MtpDevice::~MtpDevice() { 232 close(); 233 for (size_t i = 0; i < mDeviceProperties.size(); i++) 234 delete mDeviceProperties[i]; 235 usb_request_free(mRequestIn1); 236 usb_request_free(mRequestIn2); 237 usb_request_free(mRequestOut); 238 usb_request_free(mRequestIntr); 239} 240 241void MtpDevice::initialize() { 242 openSession(); 243 mDeviceInfo = getDeviceInfo(); 244 if (mDeviceInfo) { 245 if (mDeviceInfo->mDeviceProperties) { 246 int count = mDeviceInfo->mDeviceProperties->size(); 247 for (int i = 0; i < count; i++) { 248 MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i]; 249 MtpProperty* property = getDevicePropDesc(propCode); 250 if (property) 251 mDeviceProperties.push(property); 252 } 253 } 254 } 255} 256 257void MtpDevice::close() { 258 if (mDevice) { 259 usb_device_release_interface(mDevice, mInterface); 260 usb_device_close(mDevice); 261 mDevice = NULL; 262 } 263} 264 265void MtpDevice::print() { 266 if (mDeviceInfo) { 267 mDeviceInfo->print(); 268 269 if (mDeviceInfo->mDeviceProperties) { 270 ALOGI("***** DEVICE PROPERTIES *****\n"); 271 int count = mDeviceInfo->mDeviceProperties->size(); 272 for (int i = 0; i < count; i++) { 273 MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i]; 274 MtpProperty* property = getDevicePropDesc(propCode); 275 if (property) { 276 property->print(); 277 delete property; 278 } 279 } 280 } 281 } 282 283 if (mDeviceInfo->mPlaybackFormats) { 284 ALOGI("***** OBJECT PROPERTIES *****\n"); 285 int count = mDeviceInfo->mPlaybackFormats->size(); 286 for (int i = 0; i < count; i++) { 287 MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i]; 288 ALOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format)); 289 MtpObjectPropertyList* props = getObjectPropsSupported(format); 290 if (props) { 291 for (size_t j = 0; j < props->size(); j++) { 292 MtpObjectProperty prop = (*props)[j]; 293 MtpProperty* property = getObjectPropDesc(prop, format); 294 if (property) { 295 property->print(); 296 delete property; 297 } else { 298 ALOGE("could not fetch property: %s", 299 MtpDebug::getObjectPropCodeName(prop)); 300 } 301 } 302 } 303 } 304 } 305} 306 307const char* MtpDevice::getDeviceName() { 308 if (mDevice) 309 return usb_device_get_name(mDevice); 310 else 311 return "???"; 312} 313 314bool MtpDevice::openSession() { 315 Mutex::Autolock autoLock(mMutex); 316 317 mSessionID = 0; 318 mTransactionID = 0; 319 MtpSessionID newSession = 1; 320 mRequest.reset(); 321 mRequest.setParameter(1, newSession); 322 if (!sendRequest(MTP_OPERATION_OPEN_SESSION)) 323 return false; 324 MtpResponseCode ret = readResponse(); 325 if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN) 326 newSession = mResponse.getParameter(1); 327 else if (ret != MTP_RESPONSE_OK) 328 return false; 329 330 mSessionID = newSession; 331 mTransactionID = 1; 332 return true; 333} 334 335bool MtpDevice::closeSession() { 336 // FIXME 337 return true; 338} 339 340MtpDeviceInfo* MtpDevice::getDeviceInfo() { 341 Mutex::Autolock autoLock(mMutex); 342 343 mRequest.reset(); 344 if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO)) 345 return NULL; 346 if (!readData()) 347 return NULL; 348 MtpResponseCode ret = readResponse(); 349 if (ret == MTP_RESPONSE_OK) { 350 MtpDeviceInfo* info = new MtpDeviceInfo; 351 if (info->read(mData)) 352 return info; 353 else 354 delete info; 355 } 356 return NULL; 357} 358 359MtpStorageIDList* MtpDevice::getStorageIDs() { 360 Mutex::Autolock autoLock(mMutex); 361 362 mRequest.reset(); 363 if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS)) 364 return NULL; 365 if (!readData()) 366 return NULL; 367 MtpResponseCode ret = readResponse(); 368 if (ret == MTP_RESPONSE_OK) { 369 return mData.getAUInt32(); 370 } 371 return NULL; 372} 373 374MtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) { 375 Mutex::Autolock autoLock(mMutex); 376 377 mRequest.reset(); 378 mRequest.setParameter(1, storageID); 379 if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO)) 380 return NULL; 381 if (!readData()) 382 return NULL; 383 MtpResponseCode ret = readResponse(); 384 if (ret == MTP_RESPONSE_OK) { 385 MtpStorageInfo* info = new MtpStorageInfo(storageID); 386 if (info->read(mData)) 387 return info; 388 else 389 delete info; 390 } 391 return NULL; 392} 393 394MtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID, 395 MtpObjectFormat format, MtpObjectHandle parent) { 396 Mutex::Autolock autoLock(mMutex); 397 398 mRequest.reset(); 399 mRequest.setParameter(1, storageID); 400 mRequest.setParameter(2, format); 401 mRequest.setParameter(3, parent); 402 if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES)) 403 return NULL; 404 if (!readData()) 405 return NULL; 406 MtpResponseCode ret = readResponse(); 407 if (ret == MTP_RESPONSE_OK) { 408 return mData.getAUInt32(); 409 } 410 return NULL; 411} 412 413MtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) { 414 Mutex::Autolock autoLock(mMutex); 415 416 // FIXME - we might want to add some caching here 417 418 mRequest.reset(); 419 mRequest.setParameter(1, handle); 420 if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO)) 421 return NULL; 422 if (!readData()) 423 return NULL; 424 MtpResponseCode ret = readResponse(); 425 if (ret == MTP_RESPONSE_OK) { 426 MtpObjectInfo* info = new MtpObjectInfo(handle); 427 if (info->read(mData)) 428 return info; 429 else 430 delete info; 431 } 432 return NULL; 433} 434 435void* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) { 436 Mutex::Autolock autoLock(mMutex); 437 438 mRequest.reset(); 439 mRequest.setParameter(1, handle); 440 if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) { 441 MtpResponseCode ret = readResponse(); 442 if (ret == MTP_RESPONSE_OK) { 443 return mData.getData(&outLength); 444 } 445 } 446 outLength = 0; 447 return NULL; 448} 449 450MtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) { 451 Mutex::Autolock autoLock(mMutex); 452 453 mRequest.reset(); 454 MtpObjectHandle parent = info->mParent; 455 if (parent == 0) 456 parent = MTP_PARENT_ROOT; 457 458 mRequest.setParameter(1, info->mStorageID); 459 mRequest.setParameter(2, parent); 460 461 mData.reset(); 462 mData.putUInt32(info->mStorageID); 463 mData.putUInt16(info->mFormat); 464 mData.putUInt16(info->mProtectionStatus); 465 mData.putUInt32(info->mCompressedSize); 466 mData.putUInt16(info->mThumbFormat); 467 mData.putUInt32(info->mThumbCompressedSize); 468 mData.putUInt32(info->mThumbPixWidth); 469 mData.putUInt32(info->mThumbPixHeight); 470 mData.putUInt32(info->mImagePixWidth); 471 mData.putUInt32(info->mImagePixHeight); 472 mData.putUInt32(info->mImagePixDepth); 473 mData.putUInt32(info->mParent); 474 mData.putUInt16(info->mAssociationType); 475 mData.putUInt32(info->mAssociationDesc); 476 mData.putUInt32(info->mSequenceNumber); 477 mData.putString(info->mName); 478 479 char created[100], modified[100]; 480 formatDateTime(info->mDateCreated, created, sizeof(created)); 481 formatDateTime(info->mDateModified, modified, sizeof(modified)); 482 483 mData.putString(created); 484 mData.putString(modified); 485 if (info->mKeywords) 486 mData.putString(info->mKeywords); 487 else 488 mData.putEmptyString(); 489 490 if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) { 491 MtpResponseCode ret = readResponse(); 492 if (ret == MTP_RESPONSE_OK) { 493 info->mStorageID = mResponse.getParameter(1); 494 info->mParent = mResponse.getParameter(2); 495 info->mHandle = mResponse.getParameter(3); 496 return info->mHandle; 497 } 498 } 499 return (MtpObjectHandle)-1; 500} 501 502bool MtpDevice::sendObject(MtpObjectHandle handle, int size, int srcFD) { 503 Mutex::Autolock autoLock(mMutex); 504 505 int remaining = size; 506 mRequest.reset(); 507 mRequest.setParameter(1, handle); 508 if (sendRequest(MTP_OPERATION_SEND_OBJECT)) { 509 // send data header 510 writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining); 511 512 // USB writes greater than 16K don't work 513 char buffer[MTP_BUFFER_SIZE]; 514 while (remaining > 0) { 515 int count = read(srcFD, buffer, sizeof(buffer)); 516 if (count > 0) { 517 int written = mData.write(mRequestOut, buffer, count); 518 // FIXME check error 519 remaining -= count; 520 } else { 521 break; 522 } 523 } 524 } 525 MtpResponseCode ret = readResponse(); 526 return (remaining == 0 && ret == MTP_RESPONSE_OK); 527} 528 529bool MtpDevice::deleteObject(MtpObjectHandle handle) { 530 Mutex::Autolock autoLock(mMutex); 531 532 mRequest.reset(); 533 mRequest.setParameter(1, handle); 534 if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) { 535 MtpResponseCode ret = readResponse(); 536 if (ret == MTP_RESPONSE_OK) 537 return true; 538 } 539 return false; 540} 541 542MtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) { 543 MtpObjectInfo* info = getObjectInfo(handle); 544 if (info) { 545 MtpObjectHandle parent = info->mParent; 546 delete info; 547 return parent; 548 } else { 549 return -1; 550 } 551} 552 553MtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) { 554 MtpObjectInfo* info = getObjectInfo(handle); 555 if (info) { 556 MtpObjectHandle storageId = info->mStorageID; 557 delete info; 558 return storageId; 559 } else { 560 return -1; 561 } 562} 563 564MtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) { 565 Mutex::Autolock autoLock(mMutex); 566 567 mRequest.reset(); 568 mRequest.setParameter(1, format); 569 if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED)) 570 return NULL; 571 if (!readData()) 572 return NULL; 573 MtpResponseCode ret = readResponse(); 574 if (ret == MTP_RESPONSE_OK) { 575 return mData.getAUInt16(); 576 } 577 return NULL; 578 579} 580 581MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) { 582 Mutex::Autolock autoLock(mMutex); 583 584 mRequest.reset(); 585 mRequest.setParameter(1, code); 586 if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC)) 587 return NULL; 588 if (!readData()) 589 return NULL; 590 MtpResponseCode ret = readResponse(); 591 if (ret == MTP_RESPONSE_OK) { 592 MtpProperty* property = new MtpProperty; 593 if (property->read(mData)) 594 return property; 595 else 596 delete property; 597 } 598 return NULL; 599} 600 601MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) { 602 Mutex::Autolock autoLock(mMutex); 603 604 mRequest.reset(); 605 mRequest.setParameter(1, code); 606 mRequest.setParameter(2, format); 607 if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC)) 608 return NULL; 609 if (!readData()) 610 return NULL; 611 MtpResponseCode ret = readResponse(); 612 if (ret == MTP_RESPONSE_OK) { 613 MtpProperty* property = new MtpProperty; 614 if (property->read(mData)) 615 return property; 616 else 617 delete property; 618 } 619 return NULL; 620} 621 622bool MtpDevice::readObject(MtpObjectHandle handle, 623 ReadObjectCallback callback, 624 uint32_t expectedLength, 625 void* clientData) { 626 return readObjectInternal(handle, callback, &expectedLength, clientData); 627} 628 629// reads the object's data and writes it to the specified file path 630bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) { 631 ALOGD("readObject: %s", destPath); 632 int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 633 if (fd < 0) { 634 ALOGE("open failed for %s", destPath); 635 return false; 636 } 637 638 fchown(fd, getuid(), group); 639 // set permissions 640 int mask = umask(0); 641 fchmod(fd, perm); 642 umask(mask); 643 644 bool result = readObject(handle, fd); 645 ::close(fd); 646 return result; 647} 648 649bool MtpDevice::readObject(MtpObjectHandle handle, int fd) { 650 ALOGD("readObject: %d", fd); 651 return readObjectInternal(handle, writeToFd, NULL /* expected size */, &fd); 652} 653 654bool MtpDevice::readObjectInternal(MtpObjectHandle handle, 655 ReadObjectCallback callback, 656 const uint32_t* expectedLength, 657 void* clientData) { 658 Mutex::Autolock autoLock(mMutex); 659 660 mRequest.reset(); 661 mRequest.setParameter(1, handle); 662 if (!sendRequest(MTP_OPERATION_GET_OBJECT)) { 663 ALOGE("Failed to send a read request."); 664 return false; 665 } 666 667 return readData(callback, expectedLength, nullptr, clientData); 668} 669 670bool MtpDevice::readData(ReadObjectCallback callback, 671 const uint32_t* expectedLength, 672 uint32_t* writtenSize, 673 void* clientData) { 674 if (!mData.readDataHeader(mRequestIn1)) { 675 ALOGE("Failed to read header."); 676 return false; 677 } 678 679 if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) { 680 mResponse.copyFrom(mData); 681 return mResponse.getResponseCode() == MTP_RESPONSE_OK ? 0 : -1; 682 } 683 684 // If object size 0 byte, the remote device can reply response packet 685 // without sending any data packets. 686 if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) { 687 mResponse.copyFrom(mData); 688 return mResponse.getResponseCode() == MTP_RESPONSE_OK; 689 } 690 691 const uint32_t fullLength = mData.getContainerLength(); 692 if (fullLength < MTP_CONTAINER_HEADER_SIZE) { 693 ALOGE("fullLength is too short: %d", fullLength); 694 return false; 695 } 696 const uint32_t length = fullLength - MTP_CONTAINER_HEADER_SIZE; 697 if (expectedLength && length != *expectedLength) { 698 ALOGE("readObject error length: %d", fullLength); 699 return false; 700 } 701 702 uint32_t offset = 0; 703 bool writingError = false; 704 705 { 706 int initialDataLength = 0; 707 void* const initialData = mData.getData(&initialDataLength); 708 if (initialData) { 709 if (initialDataLength > 0) { 710 if (!callback(initialData, offset, initialDataLength, clientData)) { 711 ALOGE("Failed to write initial data."); 712 writingError = true; 713 } 714 offset += initialDataLength; 715 } 716 free(initialData); 717 } 718 } 719 720 // USB reads greater than 16K don't work. 721 char buffer1[MTP_BUFFER_SIZE], buffer2[MTP_BUFFER_SIZE]; 722 mRequestIn1->buffer = buffer1; 723 mRequestIn2->buffer = buffer2; 724 struct usb_request* req = NULL; 725 726 while (offset < length) { 727 // Wait for previous read to complete. 728 void* writeBuffer = NULL; 729 int writeLength = 0; 730 if (req) { 731 const int read = mData.readDataWait(mDevice); 732 if (read < 0) { 733 ALOGE("readDataWait failed."); 734 return false; 735 } 736 writeBuffer = req->buffer; 737 writeLength = read; 738 } 739 740 // Request to read next chunk. 741 const uint32_t nextOffset = offset + writeLength; 742 if (nextOffset < length) { 743 // Queue up a read request. 744 const size_t remaining = length - nextOffset; 745 req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1); 746 req->buffer_length = remaining > MTP_BUFFER_SIZE ? 747 static_cast<size_t>(MTP_BUFFER_SIZE) : remaining; 748 if (mData.readDataAsync(req) != 0) { 749 ALOGE("readDataAsync failed"); 750 return false; 751 } 752 } 753 754 // Write previous buffer. 755 if (writeBuffer && !writingError) { 756 if (!callback(writeBuffer, offset, writeLength, clientData)) { 757 ALOGE("write failed"); 758 writingError = true; 759 } 760 } 761 offset = nextOffset; 762 } 763 764 if (writtenSize) { 765 *writtenSize = length; 766 } 767 768 return readResponse() == MTP_RESPONSE_OK; 769} 770 771bool MtpDevice::readPartialObject(MtpObjectHandle handle, 772 uint32_t offset, 773 uint32_t size, 774 uint32_t *writtenSize, 775 ReadObjectCallback callback, 776 void* clientData) { 777 Mutex::Autolock autoLock(mMutex); 778 779 mRequest.reset(); 780 mRequest.setParameter(1, handle); 781 mRequest.setParameter(2, offset); 782 mRequest.setParameter(3, size); 783 if (!sendRequest(MTP_OPERATION_GET_PARTIAL_OBJECT)) { 784 ALOGE("Failed to send a read request."); 785 return false; 786 } 787 return readData(callback, NULL /* expected size */, writtenSize, clientData); 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 858int MtpDevice::submitEventRequest() { 859 if (mEventMutex.tryLock()) { 860 // An event is being reaped on another thread. 861 return -1; 862 } 863 if (mProcessingEvent) { 864 // An event request was submitted, but no reapEventRequest called so far. 865 return -1; 866 } 867 Mutex::Autolock autoLock(mEventMutexForInterrupt); 868 mEventPacket.sendRequest(mRequestIntr); 869 const int currentHandle = ++mCurrentEventHandle; 870 mProcessingEvent = true; 871 mEventMutex.unlock(); 872 return currentHandle; 873} 874 875int MtpDevice::reapEventRequest(int handle, uint32_t (*parameters)[3]) { 876 Mutex::Autolock autoLock(mEventMutex); 877 if (!mProcessingEvent || mCurrentEventHandle != handle || !parameters) { 878 return -1; 879 } 880 mProcessingEvent = false; 881 const int readSize = mEventPacket.readResponse(mRequestIntr->dev); 882 const int result = mEventPacket.getEventCode(); 883 // MTP event has three parameters. 884 (*parameters)[0] = mEventPacket.getParameter(1); 885 (*parameters)[1] = mEventPacket.getParameter(2); 886 (*parameters)[2] = mEventPacket.getParameter(3); 887 return readSize != 0 ? result : 0; 888} 889 890void MtpDevice::discardEventRequest(int handle) { 891 Mutex::Autolock autoLock(mEventMutexForInterrupt); 892 if (mCurrentEventHandle != handle) { 893 return; 894 } 895 usb_request_cancel(mRequestIntr); 896} 897 898} // namespace android 899