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