Merge "MTP: Add support for sending events to the host when objects are added and removed"

This commit is contained in:
Mike Lockwood
2010-07-13 17:14:45 -07:00
committed by Android (Google) Code Review
9 changed files with 224 additions and 12 deletions

View File

@@ -47,6 +47,14 @@ public class MtpServer {
native_stop();
}
public void sendObjectAdded(int handle) {
native_send_object_added(handle);
}
public void sendObjectRemoved(int handle) {
native_send_object_removed(handle);
}
// used by the JNI code
private int mNativeContext;
@@ -54,4 +62,6 @@ public class MtpServer {
private native final void native_finalize();
private native final void native_start();
private native final void native_stop();
private native final void native_send_object_added(int handle);
private native final void native_send_object_removed(int handle);
}

View File

@@ -50,12 +50,14 @@ static bool ExceptionCheck(void* env)
class MtpThread : public Thread {
private:
MtpDatabase* mDatabase;
MtpServer* mServer;
String8 mStoragePath;
bool mDone;
Mutex mMutex;
public:
MtpThread(MtpDatabase* database, const char* storagePath)
: mDatabase(database), mStoragePath(storagePath), mDone(false)
: mDatabase(database), mServer(NULL), mStoragePath(storagePath), mDone(false)
{
}
@@ -67,14 +69,19 @@ public:
return false;
}
MtpServer* server = new MtpServer(fd, mDatabase, AID_SDCARD_RW, 0664, 0775);
server->addStorage(mStoragePath);
mMutex.lock();
mServer = new MtpServer(fd, mDatabase, AID_SDCARD_RW, 0664, 0775);
mServer->addStorage(mStoragePath);
mMutex.unlock();
// temporary
LOGD("MtpThread server->run");
server->run();
LOGD("MtpThread mServer->run");
mServer->run();
close(fd);
delete server;
mMutex.lock();
delete mServer;
mServer = NULL;
mMutex.unlock();
bool done = mDone;
if (done)
@@ -84,6 +91,24 @@ public:
}
void setDone() { mDone = true; }
void sendObjectAdded(MtpObjectHandle handle) {
mMutex.lock();
if (mServer)
mServer->sendObjectAdded(handle);
else
LOGE("sendObjectAdded called while disconnected\n");
mMutex.unlock();
}
void sendObjectRemoved(MtpObjectHandle handle) {
mMutex.lock();
if (mServer)
mServer->sendObjectRemoved(handle);
else
LOGE("sendObjectRemoved called while disconnected\n");
mMutex.unlock();
}
};
static void
@@ -126,14 +151,38 @@ android_media_MtpServer_stop(JNIEnv *env, jobject thiz)
}
}
static void
android_media_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
{
LOGD("send_object_added %d\n", handle);
MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
if (thread)
thread->sendObjectAdded(handle);
else
LOGE("sendObjectAdded called while disconnected\n");
}
static void
android_media_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
{
LOGD("send_object_removed %d\n", handle);
MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
if (thread)
thread->sendObjectRemoved(handle);
else
LOGE("sendObjectRemoved called while disconnected\n");
}
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
{"native_setup", "(Landroid/media/MtpDatabase;Ljava/lang/String;)V",
{"native_setup", "(Landroid/media/MtpDatabase;Ljava/lang/String;)V",
(void *)android_media_MtpServer_setup},
{"native_finalize", "()V", (void *)android_media_MtpServer_finalize},
{"native_start", "()V", (void *)android_media_MtpServer_start},
{"native_stop", "()V", (void *)android_media_MtpServer_stop},
{"native_finalize", "()V", (void *)android_media_MtpServer_finalize},
{"native_start", "()V", (void *)android_media_MtpServer_start},
{"native_stop", "()V", (void *)android_media_MtpServer_stop},
{"native_send_object_added", "(I)V", (void *)android_media_MtpServer_send_object_added},
{"native_send_object_removed", "(I)V", (void *)android_media_MtpServer_send_object_removed},
};
static const char* const kClassPathName = "android/media/MtpServer";

View File

@@ -23,6 +23,7 @@ LOCAL_SRC_FILES:= \
MtpDataPacket.cpp \
MtpDebug.cpp \
MtpDevice.cpp \
MtpEventPacket.cpp \
MtpDeviceInfo.cpp \
MtpObjectInfo.cpp \
MtpPacket.cpp \

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "MtpEventPacket"
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <f_mtp.h>
#include "MtpEventPacket.h"
namespace android {
MtpEventPacket::MtpEventPacket()
: MtpPacket(512)
{
}
MtpEventPacket::~MtpEventPacket() {
}
#ifdef MTP_DEVICE
int MtpEventPacket::write(int fd) {
struct mtp_event event;
putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_EVENT);
event.data = mBuffer;
event.length = mPacketSize;
int ret = ::ioctl(fd, MTP_SEND_EVENT, (unsigned long)&event);
return (ret < 0 ? ret : 0);
}
#endif
#ifdef MTP_HOST
// read our buffer from the given endpoint
int MtpEventPacket::read(struct usb_endpoint *ep) {
int ret = transfer(ep, mBuffer, mBufferSize);
if (ret >= 0)
mPacketSize = ret;
else
mPacketSize = 0;
return ret;
}
#endif
} // namespace android

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _MTP_EVENT_PACKET_H
#define _MTP_EVENT_PACKET_H
#include "MtpPacket.h"
#include "mtp.h"
namespace android {
class MtpEventPacket : public MtpPacket {
public:
MtpEventPacket();
virtual ~MtpEventPacket();
#ifdef MTP_DEVICE
// write our data to the given file descriptor
int write(int fd);
#endif
#ifdef MTP_HOST
// read our buffer from the given endpoint
int read(struct usb_endpoint *ep);
#endif
inline MtpEventCode getEventCode() const { return getContainerCode(); }
inline void setEventCode(MtpEventCode code)
{ return setContainerCode(code); }
};
}; // namespace android
#endif // _MTP_EVENT_PACKET_H

View File

@@ -73,6 +73,11 @@ static const MtpOperationCode kSupportedOperationCodes[] = {
// MTP_OPERATION_SKIP,
};
static const MtpEventCode kSupportedEventCodes[] = {
MTP_EVENT_OBJECT_ADDED,
MTP_EVENT_OBJECT_REMOVED,
};
static const MtpObjectProperty kSupportedObjectProperties[] = {
MTP_PROPERTY_STORAGE_ID,
MTP_PROPERTY_OBJECT_FORMAT,
@@ -239,6 +244,24 @@ MtpProperty* MtpServer::getDeviceProperty(MtpPropertyCode propCode) {
return NULL;
}
void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
LOGD("sendObjectAdded %d\n", handle);
mEvent.setEventCode(MTP_EVENT_OBJECT_ADDED);
mEvent.setTransactionID(mRequest.getTransactionID());
mEvent.setParameter(1, handle);
int ret = mEvent.write(mFD);
LOGD("mEvent.write returned %d\n", ret);
}
void MtpServer::sendObjectRemoved(MtpObjectHandle handle) {
LOGD("sendObjectRemoved %d\n", handle);
mEvent.setEventCode(MTP_EVENT_OBJECT_REMOVED);
mEvent.setTransactionID(mRequest.getTransactionID());
mEvent.setParameter(1, handle);
int ret = mEvent.write(mFD);
LOGD("mEvent.write returned %d\n", ret);
}
void MtpServer::initObjectProperties() {
mObjectProperties.push(new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT16));
mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16));
@@ -326,7 +349,8 @@ MtpResponseCode MtpServer::doGetDeviceInfo() {
mData.putUInt16(0); //Functional Mode
mData.putAUInt16(kSupportedOperationCodes,
sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported
mData.putEmptyArray(); // Events Supported
mData.putAUInt16(kSupportedEventCodes,
sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported
mData.putEmptyArray(); // Device Properties Supported
mData.putEmptyArray(); // Capture Formats
mData.putAUInt16(kSupportedPlaybackFormats,

View File

@@ -20,6 +20,7 @@
#include "MtpRequestPacket.h"
#include "MtpDataPacket.h"
#include "MtpResponsePacket.h"
#include "MtpEventPacket.h"
#include "mtp.h"
#include "MtpUtils.h"
@@ -52,6 +53,7 @@ private:
MtpRequestPacket mRequest;
MtpDataPacket mData;
MtpResponsePacket mResponse;
MtpEventPacket mEvent;
MtpStorageList mStorages;
@@ -77,6 +79,9 @@ public:
MtpProperty* getObjectProperty(MtpPropertyCode propCode);
MtpProperty* getDeviceProperty(MtpPropertyCode propCode);
void sendObjectAdded(MtpObjectHandle handle);
void sendObjectRemoved(MtpObjectHandle handle);
private:
void initObjectProperties();

View File

@@ -28,6 +28,7 @@ typedef uint32_t uint128_t[4];
typedef uint16_t MtpOperationCode;
typedef uint16_t MtpResponseCode;
typedef uint16_t MtpEventCode;
typedef uint32_t MtpSessionID;
typedef uint32_t MtpStorageID;
typedef uint32_t MtpTransactionID;

View File

@@ -32,6 +32,13 @@ struct mtp_file_range {
size_t length;
};
struct mtp_event {
/* size of the event */
size_t length;
/* event data to send */
void *data;
};
/* Sends the specified file range to the host */
#define MTP_SEND_FILE _IOW('M', 0, struct mtp_file_range)
/* Receives data from the host and writes it to a file.
@@ -40,5 +47,7 @@ struct mtp_file_range {
#define MTP_RECEIVE_FILE _IOW('M', 1, struct mtp_file_range)
/* Sets the driver mode to either MTP or PTP */
#define MTP_SET_INTERFACE_MODE _IOW('M', 2, int)
/* Sends an event to the host via the interrupt endpoint */
#define MTP_SEND_EVENT _IOW('M', 3, struct mtp_event)
#endif /* __LINUX_USB_F_MTP_H */