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