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