Add functions to read MTP events from MTP devices.
BUG=23368533
Change-Id: I2003dda961339677caf56e57ae90cf6df7bd7430
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 9878f90..01117e6 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -204,7 +204,9 @@
mDeviceInfo(NULL),
mSessionID(0),
mTransactionID(0),
- mReceivedResponse(false)
+ mReceivedResponse(false),
+ mProcessingEvent(false),
+ mCurrentEventHandle(0)
{
mRequestIn1 = usb_request_new(device, ep_in);
mRequestIn2 = usb_request_new(device, ep_in);
@@ -794,4 +796,40 @@
}
}
+int MtpDevice::submitEventRequest() {
+ if (mEventMutex.tryLock()) {
+ // An event is being reaped on another thread.
+ return -1;
+ }
+ if (mProcessingEvent) {
+ // An event request was submitted, but no reapEventRequest called so far.
+ return -1;
+ }
+ Mutex::Autolock autoLock(mEventMutexForInterrupt);
+ mEventPacket.sendRequest(mRequestIntr);
+ const int currentHandle = ++mCurrentEventHandle;
+ mProcessingEvent = true;
+ mEventMutex.unlock();
+ return currentHandle;
+}
+
+int MtpDevice::reapEventRequest(int handle) {
+ Mutex::Autolock autoLock(mEventMutex);
+ if (!mProcessingEvent || mCurrentEventHandle != handle) {
+ return -1;
+ }
+ mProcessingEvent = false;
+ const int readSize = mEventPacket.readResponse(mRequestIntr->dev);
+ const int result = mEventPacket.getEventCode();
+ return readSize == 0 ? 0 : result;
+}
+
+void MtpDevice::discardEventRequest(int handle) {
+ Mutex::Autolock autoLock(mEventMutexForInterrupt);
+ if (mCurrentEventHandle != handle) {
+ return;
+ }
+ usb_request_cancel(mRequestIntr);
+}
+
} // namespace android
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index d2c6d67..87b3b90 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -17,8 +17,9 @@
#ifndef _MTP_DEVICE_H
#define _MTP_DEVICE_H
-#include "MtpRequestPacket.h"
+#include "MtpEventPacket.h"
#include "MtpDataPacket.h"
+#include "MtpRequestPacket.h"
#include "MtpResponsePacket.h"
#include "MtpTypes.h"
@@ -31,6 +32,7 @@
namespace android {
class MtpDeviceInfo;
+class MtpEventPacket;
class MtpObjectInfo;
class MtpStorageInfo;
@@ -53,11 +55,17 @@
MtpRequestPacket mRequest;
MtpDataPacket mData;
MtpResponsePacket mResponse;
+ MtpEventPacket mEventPacket;
+
// set to true if we received a response packet instead of a data packet
bool mReceivedResponse;
+ bool mProcessingEvent;
+ int mCurrentEventHandle;
// to ensure only one MTP transaction at a time
Mutex mMutex;
+ Mutex mEventMutex;
+ Mutex mEventMutexForInterrupt;
public:
typedef bool (*ReadObjectCallback)(void* data, int offset, int length, void* clientData);
@@ -101,6 +109,18 @@
bool readObject(MtpObjectHandle handle, const char* destPath, int group,
int perm);
bool readObject(MtpObjectHandle handle, int fd);
+ // Starts a request to read MTP event from MTP device. It returns a request handle that
+ // can be used for blocking read or cancel. If other thread has already been processing an
+ // event returns -1.
+ int submitEventRequest();
+ // Waits for MTP event from the device and returns MTP event code. It blocks the current thread
+ // until it receives an event from the device. |handle| should be a request handle returned
+ // by |submitEventRequest|. Returns 0 for cancellations. Returns -1 for errors.
+ int reapEventRequest(int handle);
+ // Cancels an event request. |handle| should be request handle returned by
+ // |submitEventRequest|. If there is a thread blocked by |reapEventRequest| with the same
+ // |handle|, the thread will resume.
+ void discardEventRequest(int handle);
private:
// If |objectSize| is not NULL, it checks object size before reading data bytes.
@@ -111,7 +131,6 @@
bool readData();
bool writeDataHeader(MtpOperationCode operation, int dataLength);
MtpResponseCode readResponse();
-
};
}; // namespace android
diff --git a/media/mtp/MtpEventPacket.cpp b/media/mtp/MtpEventPacket.cpp
index d2fca42..8e13ea9 100644
--- a/media/mtp/MtpEventPacket.cpp
+++ b/media/mtp/MtpEventPacket.cpp
@@ -54,17 +54,26 @@
#endif
#ifdef MTP_HOST
-int MtpEventPacket::read(struct usb_request *request) {
+int MtpEventPacket::sendRequest(struct usb_request *request) {
request->buffer = mBuffer;
request->buffer_length = mBufferSize;
- int ret = transfer(request);
- if (ret >= 0)
- mPacketSize = ret;
- else
- mPacketSize = 0;
- return ret;
+ mPacketSize = 0;
+ if (usb_request_queue(request)) {
+ ALOGE("usb_endpoint_queue failed, errno: %d", errno);
+ return -1;
+ }
+ return 0;
+}
+
+int MtpEventPacket::readResponse(struct usb_device *device) {
+ struct usb_request* const req = usb_request_wait(device);
+ if (req) {
+ mPacketSize = req->actual_length;
+ return req->actual_length;
+ } else {
+ return -1;
+ }
}
#endif
} // namespace android
-
diff --git a/media/mtp/MtpEventPacket.h b/media/mtp/MtpEventPacket.h
index 660baad..a8779fd 100644
--- a/media/mtp/MtpEventPacket.h
+++ b/media/mtp/MtpEventPacket.h
@@ -35,7 +35,8 @@
#ifdef MTP_HOST
// read our buffer with the given request
- int read(struct usb_request *request);
+ int sendRequest(struct usb_request *request);
+ int readResponse(struct usb_device *device);
#endif
inline MtpEventCode getEventCode() const { return getContainerCode(); }
diff --git a/media/mtp/MtpPacket.h b/media/mtp/MtpPacket.h
index 037722a..0e96309 100644
--- a/media/mtp/MtpPacket.h
+++ b/media/mtp/MtpPacket.h
@@ -19,6 +19,7 @@
#include "MtpTypes.h"
+struct usb_device;
struct usb_request;
namespace android {