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