summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/mtp/MtpDataPacket.cpp30
-rw-r--r--media/mtp/MtpDataPacket.h3
-rw-r--r--media/mtp/MtpDevice.cpp151
-rw-r--r--media/mtp/MtpDevice.h5
4 files changed, 93 insertions, 96 deletions
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 20dd94d..e1d1a92 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -413,20 +413,32 @@ int MtpDataPacket::read(struct usb_endpoint *ep) {
}
int MtpDataPacket::readData(struct usb_endpoint *ep, void* buffer, int length) {
- int packetSize = usb_endpoint_max_packet(ep);
int read = 0;
while (read < length) {
- int ret = transfer(ep, (char *)buffer + read, packetSize);
+ int ret = transfer(ep, (char *)buffer + read, length - read);
if (ret < 0) {
-printf("MtpDataPacket::readData returning %d\n", ret);
return ret;
}
read += ret;
}
-printf("MtpDataPacket::readData returning %d\n", read);
return read;
}
+// Queue a read request. Call readDataWait to wait for result
+int MtpDataPacket::readDataAsync(struct usb_endpoint *ep, void* buffer, int length) {
+ if (usb_endpoint_queue(ep, buffer, length)) {
+ LOGE("usb_endpoint_queue failed, errno: %d", errno);
+ return -1;
+ }
+ return 0;
+}
+
+// Wait for result of readDataAsync
+int MtpDataPacket::readDataWait(struct usb_endpoint *ep) {
+ int ep_num;
+ return usb_endpoint_wait(usb_endpoint_get_device(ep), &ep_num);
+}
+
int MtpDataPacket::readDataHeader(struct usb_endpoint *ep) {
int length = transfer(ep, mBuffer, usb_endpoint_max_packet(ep));
if (length >= 0)
@@ -454,15 +466,7 @@ int MtpDataPacket::write(struct usb_endpoint *ep) {
}
int MtpDataPacket::write(struct usb_endpoint *ep, void* buffer, uint32_t length) {
- int ret = 0;
- int packetSize = usb_endpoint_max_packet(ep);
- while (length > 0) {
- int write = (length > packetSize ? packetSize : length);
- int ret = transfer(ep, buffer, write);
- if (ret < 0)
- break;
- length -= ret;
- }
+ int ret = transfer(ep, buffer, length);
return (ret < 0 ? ret : 0);
}
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index fab6a07..3ae6226 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -102,6 +102,8 @@ public:
#ifdef MTP_HOST
int read(struct usb_endpoint *ep);
int readData(struct usb_endpoint *ep, void* buffer, int length);
+ int readDataAsync(struct usb_endpoint *ep, void* buffer, int length);
+ int readDataWait(struct usb_endpoint *ep);
int readDataHeader(struct usb_endpoint *ep);
int writeDataHeader(struct usb_endpoint *ep, uint32_t length);
@@ -110,6 +112,7 @@ public:
#endif
inline bool hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; }
+ inline uint32_t getContainerLength() const { return MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET); }
void* getData(int& outLength) const;
};
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index fca0142..1b23a8e 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -348,97 +348,90 @@ MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
return NULL;
}
-class ReadObjectThread : public Thread {
-private:
- MtpDevice* mDevice;
- MtpObjectHandle mHandle;
- int mObjectSize;
- void* mInitialData;
- int mInitialDataLength;
- int mFD;
-
-public:
- ReadObjectThread(MtpDevice* device, MtpObjectHandle handle, int objectSize)
- : mDevice(device),
- mHandle(handle),
- mObjectSize(objectSize),
- mInitialData(NULL),
- mInitialDataLength(0)
- {
+// reads the object's data and writes it to the specified file path
+bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath) {
+ LOGD("readObject: %s", destPath);
+ int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC);
+ if (fd < 0) {
+ LOGE("open failed for %s", destPath);
+ return false;
}
- virtual ~ReadObjectThread() {
- if (mFD >= 0)
- close(mFD);
- free(mInitialData);
- }
+ Mutex::Autolock autoLock(mMutex);
+ bool result = false;
- // returns file descriptor
- int init() {
- mDevice->mRequest.reset();
- mDevice->mRequest.setParameter(1, mHandle);
- if (mDevice->sendRequest(MTP_OPERATION_GET_OBJECT)
- && mDevice->mData.readDataHeader(mDevice->mEndpointIn)) {
-
- // mData will contain header and possibly the beginning of the object data
- mInitialData = mDevice->mData.getData(mInitialDataLength);
-
- // create a pipe for the client to read from
- int pipefd[2];
- if (pipe(pipefd) < 0) {
- LOGE("pipe failed (%s)", strerror(errno));
- return -1;
+ mRequest.reset();
+ mRequest.setParameter(1, handle);
+ if (sendRequest(MTP_OPERATION_GET_OBJECT)
+ && mData.readDataHeader(mEndpointIn)) {
+ uint32_t length = mData.getContainerLength();
+ if (length < MTP_CONTAINER_HEADER_SIZE)
+ goto fail;
+ length -= MTP_CONTAINER_HEADER_SIZE;
+ uint32_t remaining = length;
+
+ int initialDataLength = 0;
+ void* initialData = mData.getData(initialDataLength);
+ if (initialData) {
+ if (initialDataLength > 0) {
+ if (write(fd, initialData, initialDataLength) != initialDataLength)
+ goto fail;
+ remaining -= initialDataLength;
}
-
- mFD = pipefd[1];
- return pipefd[0];
- } else {
- return -1;
- }
- }
-
- virtual bool threadLoop() {
- int remaining = mObjectSize;
- if (mInitialData) {
- write(mFD, mInitialData, mInitialDataLength);
- remaining -= mInitialDataLength;
- free(mInitialData);
- mInitialData = NULL;
+ free(initialData);
}
- char buffer[16384];
- while (remaining > 0) {
- int readSize = (remaining > sizeof(buffer) ? sizeof(buffer) : remaining);
- int count = mDevice->mData.readData(mDevice->mEndpointIn, buffer, readSize);
- int written;
- if (count >= 0) {
- int written = write(mFD, buffer, count);
- // FIXME check error
- remaining -= count;
+ // USB reads greater than 16K don't work
+ char buffer1[16384], buffer2[16384];
+ char* readBuffer = buffer1;
+ char* writeBuffer = NULL;
+ int writeLength = 0;
+
+ while (remaining > 0 || writeBuffer) {
+ if (remaining > 0) {
+ // queue up a read request
+ int readSize = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
+ if (mData.readDataAsync(mEndpointIn, readBuffer, readSize)) {
+ LOGE("readDataAsync failed");
+ goto fail;
+ }
} else {
- break;
+ readBuffer = NULL;
}
- }
- MtpResponseCode ret = mDevice->readResponse();
- mDevice->mMutex.unlock();
- return false;
- }
-};
+ if (writeBuffer) {
+ // write previous buffer
+ if (write(fd, writeBuffer, writeLength) != writeLength) {
+ LOGE("write failed");
+ // wait for pending read before failing
+ if (readBuffer)
+ mData.readDataWait(mEndpointIn);
+ goto fail;
+ }
+ writeBuffer = NULL;
+ }
- // returns the file descriptor for a pipe to read the object's data
-int MtpDevice::readObject(MtpObjectHandle handle, int objectSize) {
- mMutex.lock();
+ // wait for read to complete
+ if (readBuffer) {
+ int read = mData.readDataWait(mEndpointIn);
+ if (read < 0)
+ goto fail;
- ReadObjectThread* thread = new ReadObjectThread(this, handle, objectSize);
- int fd = thread->init();
- if (fd < 0) {
- delete thread;
- mMutex.unlock();
- } else {
- thread->run("ReadObjectThread");
+ writeBuffer = readBuffer;
+ writeLength = read;
+ remaining -= read;
+ readBuffer = (readBuffer == buffer1 ? buffer2 : buffer1);
+ }
+ }
+
+ MtpResponseCode response = readResponse();
+ if (response == MTP_RESPONSE_OK)
+ result = true;
}
- return fd;
+
+fail:
+ ::close(fd);
+ return result;
}
bool MtpDevice::sendRequest(MtpOperationCode operation) {
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index 57f492f..720502c 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -86,12 +86,9 @@ public:
MtpProperty* getDevicePropDesc(MtpDeviceProperty code);
- // returns the file descriptor for a pipe to read the object's data
- int readObject(MtpObjectHandle handle, int objectSize);
+ bool readObject(MtpObjectHandle handle, const char* destPath);
private:
- friend class ReadObjectThread;
-
bool sendRequest(MtpOperationCode operation);
bool sendData();
bool readData();