| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 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 | #include <stdio.h> | 
 | 18 | #include <stdlib.h> | 
 | 19 | #include <sys/types.h> | 
 | 20 | #include <sys/ioctl.h> | 
 | 21 | #include <sys/stat.h> | 
 | 22 | #include <fcntl.h> | 
 | 23 | #include <errno.h> | 
| Mike Lockwood | d321149 | 2010-09-13 17:15:58 -0400 | [diff] [blame] | 24 | #include <sys/stat.h> | 
 | 25 | #include <dirent.h> | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 26 |  | 
| Mike Lockwood | c42aa12 | 2010-06-14 17:58:08 -0700 | [diff] [blame] | 27 | #include <cutils/properties.h> | 
 | 28 |  | 
| Mike Lockwood | a881b44 | 2010-09-23 22:32:05 -0400 | [diff] [blame] | 29 | #define LOG_TAG "MtpServer" | 
 | 30 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 31 | #include "MtpDebug.h" | 
| Mike Lockwood | 7f53a19 | 2010-07-09 10:45:22 -0400 | [diff] [blame] | 32 | #include "MtpDatabase.h" | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 33 | #include "MtpObjectInfo.h" | 
| Mike Lockwood | 21ef7d0 | 2010-06-30 17:00:35 -0400 | [diff] [blame] | 34 | #include "MtpProperty.h" | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 35 | #include "MtpServer.h" | 
 | 36 | #include "MtpStorage.h" | 
 | 37 | #include "MtpStringBuffer.h" | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 38 |  | 
| Mike Lockwood | 8065e20 | 2010-07-15 13:36:52 -0400 | [diff] [blame] | 39 | #include <linux/usb/f_mtp.h> | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 40 |  | 
| Mike Lockwood | 7850ef9 | 2010-05-14 10:10:36 -0400 | [diff] [blame] | 41 | namespace android { | 
 | 42 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 43 | static const MtpOperationCode kSupportedOperationCodes[] = { | 
 | 44 |     MTP_OPERATION_GET_DEVICE_INFO, | 
 | 45 |     MTP_OPERATION_OPEN_SESSION, | 
 | 46 |     MTP_OPERATION_CLOSE_SESSION, | 
 | 47 |     MTP_OPERATION_GET_STORAGE_IDS, | 
 | 48 |     MTP_OPERATION_GET_STORAGE_INFO, | 
 | 49 |     MTP_OPERATION_GET_NUM_OBJECTS, | 
 | 50 |     MTP_OPERATION_GET_OBJECT_HANDLES, | 
 | 51 |     MTP_OPERATION_GET_OBJECT_INFO, | 
 | 52 |     MTP_OPERATION_GET_OBJECT, | 
| Mike Lockwood | 6400078 | 2011-04-24 18:40:17 -0700 | [diff] [blame^] | 53 |     MTP_OPERATION_GET_THUMB, | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 54 |     MTP_OPERATION_DELETE_OBJECT, | 
 | 55 |     MTP_OPERATION_SEND_OBJECT_INFO, | 
 | 56 |     MTP_OPERATION_SEND_OBJECT, | 
 | 57 | //    MTP_OPERATION_INITIATE_CAPTURE, | 
 | 58 | //    MTP_OPERATION_FORMAT_STORE, | 
 | 59 | //    MTP_OPERATION_RESET_DEVICE, | 
 | 60 | //    MTP_OPERATION_SELF_TEST, | 
 | 61 | //    MTP_OPERATION_SET_OBJECT_PROTECTION, | 
 | 62 | //    MTP_OPERATION_POWER_DOWN, | 
| Mike Lockwood | e3e76c4 | 2010-09-02 14:57:30 -0400 | [diff] [blame] | 63 |     MTP_OPERATION_GET_DEVICE_PROP_DESC, | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 64 |     MTP_OPERATION_GET_DEVICE_PROP_VALUE, | 
 | 65 |     MTP_OPERATION_SET_DEVICE_PROP_VALUE, | 
 | 66 |     MTP_OPERATION_RESET_DEVICE_PROP_VALUE, | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 67 | //    MTP_OPERATION_TERMINATE_OPEN_CAPTURE, | 
 | 68 | //    MTP_OPERATION_MOVE_OBJECT, | 
 | 69 | //    MTP_OPERATION_COPY_OBJECT, | 
| Mike Lockwood | d81ce3c | 2010-11-23 09:08:01 -0500 | [diff] [blame] | 70 |     MTP_OPERATION_GET_PARTIAL_OBJECT, | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 71 | //    MTP_OPERATION_INITIATE_OPEN_CAPTURE, | 
 | 72 |     MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED, | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 73 |     MTP_OPERATION_GET_OBJECT_PROP_DESC, | 
| Mike Lockwood | 677f570 | 2010-09-23 23:04:28 -0400 | [diff] [blame] | 74 |     MTP_OPERATION_GET_OBJECT_PROP_VALUE, | 
 | 75 |     MTP_OPERATION_SET_OBJECT_PROP_VALUE, | 
| Mike Lockwood | b6da06e | 2010-10-14 18:03:25 -0400 | [diff] [blame] | 76 |     MTP_OPERATION_GET_OBJECT_PROP_LIST, | 
 | 77 | //    MTP_OPERATION_SET_OBJECT_PROP_LIST, | 
 | 78 | //    MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC, | 
 | 79 | //    MTP_OPERATION_SEND_OBJECT_PROP_LIST, | 
| Mike Lockwood | 438344f | 2010-08-03 15:30:09 -0400 | [diff] [blame] | 80 |     MTP_OPERATION_GET_OBJECT_REFERENCES, | 
 | 81 |     MTP_OPERATION_SET_OBJECT_REFERENCES, | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 82 | //    MTP_OPERATION_SKIP, | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 83 |     // Android extension for direct file IO | 
 | 84 |     MTP_OPERATION_GET_PARTIAL_OBJECT_64, | 
 | 85 |     MTP_OPERATION_SEND_PARTIAL_OBJECT, | 
 | 86 |     MTP_OPERATION_TRUNCATE_OBJECT, | 
 | 87 |     MTP_OPERATION_BEGIN_EDIT_OBJECT, | 
 | 88 |     MTP_OPERATION_END_EDIT_OBJECT, | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 89 | }; | 
 | 90 |  | 
| Mike Lockwood | 873871f | 2010-07-12 18:54:16 -0400 | [diff] [blame] | 91 | static const MtpEventCode kSupportedEventCodes[] = { | 
 | 92 |     MTP_EVENT_OBJECT_ADDED, | 
 | 93 |     MTP_EVENT_OBJECT_REMOVED, | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 94 |     MTP_EVENT_STORE_ADDED, | 
 | 95 |     MTP_EVENT_STORE_REMOVED, | 
| Mike Lockwood | 873871f | 2010-07-12 18:54:16 -0400 | [diff] [blame] | 96 | }; | 
 | 97 |  | 
| Mike Lockwood | 1865a5d | 2010-07-03 00:44:05 -0400 | [diff] [blame] | 98 | MtpServer::MtpServer(int fd, MtpDatabase* database, | 
| Mike Lockwood | 8e2a280 | 2010-07-02 15:15:07 -0400 | [diff] [blame] | 99 |                     int fileGroup, int filePerm, int directoryPerm) | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 100 |     :   mFD(fd), | 
| Mike Lockwood | 1865a5d | 2010-07-03 00:44:05 -0400 | [diff] [blame] | 101 |         mDatabase(database), | 
| Mike Lockwood | 8e2a280 | 2010-07-02 15:15:07 -0400 | [diff] [blame] | 102 |         mFileGroup(fileGroup), | 
 | 103 |         mFilePermission(filePerm), | 
 | 104 |         mDirectoryPermission(directoryPerm), | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 105 |         mSessionID(0), | 
 | 106 |         mSessionOpen(false), | 
 | 107 |         mSendObjectHandle(kInvalidObjectHandle), | 
| Mike Lockwood | 4714b07 | 2010-07-12 08:49:01 -0400 | [diff] [blame] | 108 |         mSendObjectFormat(0), | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 109 |         mSendObjectFileSize(0) | 
 | 110 | { | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 111 | } | 
 | 112 |  | 
 | 113 | MtpServer::~MtpServer() { | 
 | 114 | } | 
 | 115 |  | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 116 | void MtpServer::addStorage(MtpStorage* storage) { | 
 | 117 |     Mutex::Autolock autoLock(mMutex); | 
 | 118 |  | 
 | 119 |     mStorages.push(storage); | 
 | 120 |     sendStoreAdded(storage->getStorageID()); | 
 | 121 | } | 
 | 122 |  | 
 | 123 | void MtpServer::removeStorage(MtpStorage* storage) { | 
 | 124 |     Mutex::Autolock autoLock(mMutex); | 
 | 125 |  | 
 | 126 |     for (int i = 0; i < mStorages.size(); i++) { | 
 | 127 |         if (mStorages[i] == storage) { | 
 | 128 |             mStorages.removeAt(i); | 
 | 129 |             sendStoreRemoved(storage->getStorageID()); | 
 | 130 |             break; | 
 | 131 |         } | 
 | 132 |     } | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 133 | } | 
 | 134 |  | 
 | 135 | MtpStorage* MtpServer::getStorage(MtpStorageID id) { | 
| Mike Lockwood | fd34626 | 2010-12-08 16:08:01 -0800 | [diff] [blame] | 136 |     if (id == 0) | 
 | 137 |         return mStorages[0]; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 138 |     for (int i = 0; i < mStorages.size(); i++) { | 
| Mike Lockwood | fd34626 | 2010-12-08 16:08:01 -0800 | [diff] [blame] | 139 |         MtpStorage* storage = mStorages[i]; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 140 |         if (storage->getStorageID() == id) | 
 | 141 |             return storage; | 
 | 142 |     } | 
 | 143 |     return NULL; | 
 | 144 | } | 
 | 145 |  | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 146 | bool MtpServer::hasStorage(MtpStorageID id) { | 
 | 147 |     if (id == 0 || id == 0xFFFFFFFF) | 
 | 148 |         return mStorages.size() > 0; | 
 | 149 |     return (getStorage(id) != NULL); | 
 | 150 | } | 
 | 151 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 152 | void MtpServer::run() { | 
 | 153 |     int fd = mFD; | 
 | 154 |  | 
| Mike Lockwood | 21ef7d0 | 2010-06-30 17:00:35 -0400 | [diff] [blame] | 155 |     LOGV("MtpServer::run fd: %d\n", fd); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 156 |  | 
 | 157 |     while (1) { | 
 | 158 |         int ret = mRequest.read(fd); | 
 | 159 |         if (ret < 0) { | 
| Mike Lockwood | 59d6ae5 | 2011-01-21 21:00:54 -0800 | [diff] [blame] | 160 |             LOGV("request read returned %d, errno: %d", ret, errno); | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 161 |             if (errno == ECANCELED) { | 
 | 162 |                 // return to top of loop and wait for next command | 
 | 163 |                 continue; | 
 | 164 |             } | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 165 |             break; | 
 | 166 |         } | 
 | 167 |         MtpOperationCode operation = mRequest.getOperationCode(); | 
 | 168 |         MtpTransactionID transaction = mRequest.getTransactionID(); | 
 | 169 |  | 
| Mike Lockwood | b14e588 | 2010-06-29 18:11:52 -0400 | [diff] [blame] | 170 |         LOGV("operation: %s", MtpDebug::getOperationCodeName(operation)); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 171 |         mRequest.dump(); | 
 | 172 |  | 
 | 173 |         // FIXME need to generalize this | 
| Mike Lockwood | 438344f | 2010-08-03 15:30:09 -0400 | [diff] [blame] | 174 |         bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 175 |                     || operation == MTP_OPERATION_SET_OBJECT_REFERENCES | 
 | 176 |                     || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE | 
 | 177 |                     || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 178 |         if (dataIn) { | 
 | 179 |             int ret = mData.read(fd); | 
 | 180 |             if (ret < 0) { | 
| Mike Lockwood | b14e588 | 2010-06-29 18:11:52 -0400 | [diff] [blame] | 181 |                 LOGE("data read returned %d, errno: %d", ret, errno); | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 182 |                 if (errno == ECANCELED) { | 
 | 183 |                     // return to top of loop and wait for next command | 
 | 184 |                     continue; | 
 | 185 |                 } | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 186 |                 break; | 
 | 187 |             } | 
| Mike Lockwood | b14e588 | 2010-06-29 18:11:52 -0400 | [diff] [blame] | 188 |             LOGV("received data:"); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 189 |             mData.dump(); | 
 | 190 |         } else { | 
 | 191 |             mData.reset(); | 
 | 192 |         } | 
 | 193 |  | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 194 |         if (handleRequest()) { | 
 | 195 |             if (!dataIn && mData.hasData()) { | 
 | 196 |                 mData.setOperationCode(operation); | 
 | 197 |                 mData.setTransactionID(transaction); | 
| Mike Lockwood | b14e588 | 2010-06-29 18:11:52 -0400 | [diff] [blame] | 198 |                 LOGV("sending data:"); | 
| Mike Lockwood | 23d2071 | 2010-10-11 17:31:44 -0400 | [diff] [blame] | 199 |                 mData.dump(); | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 200 |                 ret = mData.write(fd); | 
 | 201 |                 if (ret < 0) { | 
| Mike Lockwood | b14e588 | 2010-06-29 18:11:52 -0400 | [diff] [blame] | 202 |                     LOGE("request write returned %d, errno: %d", ret, errno); | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 203 |                     if (errno == ECANCELED) { | 
 | 204 |                         // return to top of loop and wait for next command | 
 | 205 |                         continue; | 
 | 206 |                     } | 
 | 207 |                     break; | 
 | 208 |                 } | 
 | 209 |             } | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 210 |  | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 211 |             mResponse.setTransactionID(transaction); | 
| Mike Lockwood | b14e588 | 2010-06-29 18:11:52 -0400 | [diff] [blame] | 212 |             LOGV("sending response %04X", mResponse.getResponseCode()); | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 213 |             ret = mResponse.write(fd); | 
| Mike Lockwood | 23d2071 | 2010-10-11 17:31:44 -0400 | [diff] [blame] | 214 |             mResponse.dump(); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 215 |             if (ret < 0) { | 
| Mike Lockwood | b14e588 | 2010-06-29 18:11:52 -0400 | [diff] [blame] | 216 |                 LOGE("request write returned %d, errno: %d", ret, errno); | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 217 |                 if (errno == ECANCELED) { | 
 | 218 |                     // return to top of loop and wait for next command | 
 | 219 |                     continue; | 
 | 220 |                 } | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 221 |                 break; | 
 | 222 |             } | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 223 |         } else { | 
| Mike Lockwood | 21ef7d0 | 2010-06-30 17:00:35 -0400 | [diff] [blame] | 224 |             LOGV("skipping response\n"); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 225 |         } | 
 | 226 |     } | 
| Mike Lockwood | 6b3a9d1 | 2010-08-31 16:25:12 -0400 | [diff] [blame] | 227 |  | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 228 |     // commit any open edits | 
 | 229 |     int count = mObjectEditList.size(); | 
 | 230 |     for (int i = 0; i < count; i++) { | 
 | 231 |         ObjectEdit* edit = mObjectEditList[i]; | 
 | 232 |         commitEdit(edit); | 
 | 233 |         delete edit; | 
 | 234 |     } | 
 | 235 |     mObjectEditList.clear(); | 
 | 236 |  | 
| Mike Lockwood | 6b3a9d1 | 2010-08-31 16:25:12 -0400 | [diff] [blame] | 237 |     if (mSessionOpen) | 
 | 238 |         mDatabase->sessionEnded(); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 239 | } | 
 | 240 |  | 
| Mike Lockwood | 873871f | 2010-07-12 18:54:16 -0400 | [diff] [blame] | 241 | void MtpServer::sendObjectAdded(MtpObjectHandle handle) { | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 242 |     LOGV("sendObjectAdded %d\n", handle); | 
 | 243 |     sendEvent(MTP_EVENT_OBJECT_ADDED, handle); | 
| Mike Lockwood | 873871f | 2010-07-12 18:54:16 -0400 | [diff] [blame] | 244 | } | 
 | 245 |  | 
 | 246 | void MtpServer::sendObjectRemoved(MtpObjectHandle handle) { | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 247 |     LOGV("sendObjectRemoved %d\n", handle); | 
 | 248 |     sendEvent(MTP_EVENT_OBJECT_REMOVED, handle); | 
 | 249 | } | 
 | 250 |  | 
 | 251 | void MtpServer::sendStoreAdded(MtpStorageID id) { | 
 | 252 |     LOGV("sendStoreAdded %08X\n", id); | 
 | 253 |     sendEvent(MTP_EVENT_STORE_ADDED, id); | 
 | 254 | } | 
 | 255 |  | 
 | 256 | void MtpServer::sendStoreRemoved(MtpStorageID id) { | 
 | 257 |     LOGV("sendStoreRemoved %08X\n", id); | 
 | 258 |     sendEvent(MTP_EVENT_STORE_REMOVED, id); | 
 | 259 | } | 
 | 260 |  | 
 | 261 | void MtpServer::sendEvent(MtpEventCode code, uint32_t param1) { | 
| Mike Lockwood | 73ecd23 | 2010-07-19 14:29:58 -0400 | [diff] [blame] | 262 |     if (mSessionOpen) { | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 263 |         mEvent.setEventCode(code); | 
| Mike Lockwood | 73ecd23 | 2010-07-19 14:29:58 -0400 | [diff] [blame] | 264 |         mEvent.setTransactionID(mRequest.getTransactionID()); | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 265 |         mEvent.setParameter(1, param1); | 
| Mike Lockwood | 73ecd23 | 2010-07-19 14:29:58 -0400 | [diff] [blame] | 266 |         int ret = mEvent.write(mFD); | 
| Mike Lockwood | 59d6ae5 | 2011-01-21 21:00:54 -0800 | [diff] [blame] | 267 |         LOGV("mEvent.write returned %d\n", ret); | 
| Mike Lockwood | 73ecd23 | 2010-07-19 14:29:58 -0400 | [diff] [blame] | 268 |     } | 
| Mike Lockwood | 873871f | 2010-07-12 18:54:16 -0400 | [diff] [blame] | 269 | } | 
 | 270 |  | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 271 | void MtpServer::addEditObject(MtpObjectHandle handle, MtpString& path, | 
 | 272 |         uint64_t size, MtpObjectFormat format, int fd) { | 
| Mike Lockwood | c3f16e5 | 2011-04-25 12:56:21 -0700 | [diff] [blame] | 273 |     ObjectEdit*  edit = new ObjectEdit(handle, path, size, format, fd); | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 274 |     mObjectEditList.add(edit); | 
 | 275 | } | 
 | 276 |  | 
 | 277 | MtpServer::ObjectEdit* MtpServer::getEditObject(MtpObjectHandle handle) { | 
 | 278 |     int count = mObjectEditList.size(); | 
 | 279 |     for (int i = 0; i < count; i++) { | 
 | 280 |         ObjectEdit* edit = mObjectEditList[i]; | 
| Mike Lockwood | c3f16e5 | 2011-04-25 12:56:21 -0700 | [diff] [blame] | 281 |         if (edit->mHandle == handle) return edit; | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 282 |     } | 
 | 283 |     return NULL; | 
 | 284 | } | 
 | 285 |  | 
 | 286 | void MtpServer::removeEditObject(MtpObjectHandle handle) { | 
 | 287 |     int count = mObjectEditList.size(); | 
 | 288 |     for (int i = 0; i < count; i++) { | 
 | 289 |         ObjectEdit* edit = mObjectEditList[i]; | 
| Mike Lockwood | c3f16e5 | 2011-04-25 12:56:21 -0700 | [diff] [blame] | 290 |         if (edit->mHandle == handle) { | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 291 |             delete edit; | 
 | 292 |             mObjectEditList.removeAt(i); | 
 | 293 |             return; | 
 | 294 |         } | 
 | 295 |     } | 
 | 296 |     LOGE("ObjectEdit not found in removeEditObject"); | 
 | 297 | } | 
 | 298 |  | 
 | 299 | void MtpServer::commitEdit(ObjectEdit* edit) { | 
| Mike Lockwood | c3f16e5 | 2011-04-25 12:56:21 -0700 | [diff] [blame] | 300 |     mDatabase->endSendObject((const char *)edit->mPath, edit->mHandle, edit->mFormat, true); | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 301 | } | 
 | 302 |  | 
 | 303 |  | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 304 | bool MtpServer::handleRequest() { | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 305 |     Mutex::Autolock autoLock(mMutex); | 
 | 306 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 307 |     MtpOperationCode operation = mRequest.getOperationCode(); | 
 | 308 |     MtpResponseCode response; | 
 | 309 |  | 
 | 310 |     mResponse.reset(); | 
 | 311 |  | 
 | 312 |     if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) { | 
 | 313 |         // FIXME - need to delete mSendObjectHandle from the database | 
| Mike Lockwood | b14e588 | 2010-06-29 18:11:52 -0400 | [diff] [blame] | 314 |         LOGE("expected SendObject after SendObjectInfo"); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 315 |         mSendObjectHandle = kInvalidObjectHandle; | 
 | 316 |     } | 
 | 317 |  | 
 | 318 |     switch (operation) { | 
 | 319 |         case MTP_OPERATION_GET_DEVICE_INFO: | 
 | 320 |             response = doGetDeviceInfo(); | 
 | 321 |             break; | 
 | 322 |         case MTP_OPERATION_OPEN_SESSION: | 
 | 323 |             response = doOpenSession(); | 
 | 324 |             break; | 
 | 325 |         case MTP_OPERATION_CLOSE_SESSION: | 
 | 326 |             response = doCloseSession(); | 
 | 327 |             break; | 
 | 328 |         case MTP_OPERATION_GET_STORAGE_IDS: | 
 | 329 |             response = doGetStorageIDs(); | 
 | 330 |             break; | 
 | 331 |          case MTP_OPERATION_GET_STORAGE_INFO: | 
 | 332 |             response = doGetStorageInfo(); | 
 | 333 |             break; | 
 | 334 |         case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED: | 
 | 335 |             response = doGetObjectPropsSupported(); | 
 | 336 |             break; | 
 | 337 |         case MTP_OPERATION_GET_OBJECT_HANDLES: | 
 | 338 |             response = doGetObjectHandles(); | 
 | 339 |             break; | 
| Mike Lockwood | 343af4e | 2010-08-02 10:52:20 -0400 | [diff] [blame] | 340 |         case MTP_OPERATION_GET_NUM_OBJECTS: | 
 | 341 |             response = doGetNumObjects(); | 
 | 342 |             break; | 
| Mike Lockwood | 438344f | 2010-08-03 15:30:09 -0400 | [diff] [blame] | 343 |         case MTP_OPERATION_GET_OBJECT_REFERENCES: | 
 | 344 |             response = doGetObjectReferences(); | 
 | 345 |             break; | 
 | 346 |         case MTP_OPERATION_SET_OBJECT_REFERENCES: | 
 | 347 |             response = doSetObjectReferences(); | 
 | 348 |             break; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 349 |         case MTP_OPERATION_GET_OBJECT_PROP_VALUE: | 
 | 350 |             response = doGetObjectPropValue(); | 
 | 351 |             break; | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 352 |         case MTP_OPERATION_SET_OBJECT_PROP_VALUE: | 
 | 353 |             response = doSetObjectPropValue(); | 
 | 354 |             break; | 
 | 355 |         case MTP_OPERATION_GET_DEVICE_PROP_VALUE: | 
 | 356 |             response = doGetDevicePropValue(); | 
 | 357 |             break; | 
 | 358 |         case MTP_OPERATION_SET_DEVICE_PROP_VALUE: | 
 | 359 |             response = doSetDevicePropValue(); | 
 | 360 |             break; | 
 | 361 |         case MTP_OPERATION_RESET_DEVICE_PROP_VALUE: | 
 | 362 |             response = doResetDevicePropValue(); | 
 | 363 |             break; | 
| Mike Lockwood | b6da06e | 2010-10-14 18:03:25 -0400 | [diff] [blame] | 364 |         case MTP_OPERATION_GET_OBJECT_PROP_LIST: | 
 | 365 |             response = doGetObjectPropList(); | 
 | 366 |             break; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 367 |         case MTP_OPERATION_GET_OBJECT_INFO: | 
 | 368 |             response = doGetObjectInfo(); | 
 | 369 |             break; | 
 | 370 |         case MTP_OPERATION_GET_OBJECT: | 
 | 371 |             response = doGetObject(); | 
 | 372 |             break; | 
| Mike Lockwood | 6400078 | 2011-04-24 18:40:17 -0700 | [diff] [blame^] | 373 |         case MTP_OPERATION_GET_THUMB: | 
 | 374 |             response = doGetThumb(); | 
 | 375 |             break; | 
| Mike Lockwood | d81ce3c | 2010-11-23 09:08:01 -0500 | [diff] [blame] | 376 |         case MTP_OPERATION_GET_PARTIAL_OBJECT: | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 377 |         case MTP_OPERATION_GET_PARTIAL_OBJECT_64: | 
 | 378 |             response = doGetPartialObject(operation); | 
| Mike Lockwood | d81ce3c | 2010-11-23 09:08:01 -0500 | [diff] [blame] | 379 |             break; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 380 |         case MTP_OPERATION_SEND_OBJECT_INFO: | 
 | 381 |             response = doSendObjectInfo(); | 
 | 382 |             break; | 
 | 383 |         case MTP_OPERATION_SEND_OBJECT: | 
 | 384 |             response = doSendObject(); | 
 | 385 |             break; | 
 | 386 |         case MTP_OPERATION_DELETE_OBJECT: | 
 | 387 |             response = doDeleteObject(); | 
 | 388 |             break; | 
 | 389 |         case MTP_OPERATION_GET_OBJECT_PROP_DESC: | 
| Mike Lockwood | 21ef7d0 | 2010-06-30 17:00:35 -0400 | [diff] [blame] | 390 |             response = doGetObjectPropDesc(); | 
 | 391 |             break; | 
| Mike Lockwood | e3e76c4 | 2010-09-02 14:57:30 -0400 | [diff] [blame] | 392 |         case MTP_OPERATION_GET_DEVICE_PROP_DESC: | 
 | 393 |             response = doGetDevicePropDesc(); | 
 | 394 |             break; | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 395 |         case MTP_OPERATION_SEND_PARTIAL_OBJECT: | 
 | 396 |             response = doSendPartialObject(); | 
 | 397 |             break; | 
 | 398 |         case MTP_OPERATION_TRUNCATE_OBJECT: | 
 | 399 |             response = doTruncateObject(); | 
 | 400 |             break; | 
 | 401 |         case MTP_OPERATION_BEGIN_EDIT_OBJECT: | 
 | 402 |             response = doBeginEditObject(); | 
 | 403 |             break; | 
 | 404 |         case MTP_OPERATION_END_EDIT_OBJECT: | 
 | 405 |             response = doEndEditObject(); | 
 | 406 |             break; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 407 |         default: | 
| Mike Lockwood | a881b44 | 2010-09-23 22:32:05 -0400 | [diff] [blame] | 408 |             LOGE("got unsupported command %s", MtpDebug::getOperationCodeName(operation)); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 409 |             response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED; | 
 | 410 |             break; | 
 | 411 |     } | 
 | 412 |  | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 413 |     if (response == MTP_RESPONSE_TRANSACTION_CANCELLED) | 
 | 414 |         return false; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 415 |     mResponse.setResponseCode(response); | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 416 |     return true; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 417 | } | 
 | 418 |  | 
 | 419 | MtpResponseCode MtpServer::doGetDeviceInfo() { | 
 | 420 |     MtpStringBuffer   string; | 
| Mike Lockwood | c42aa12 | 2010-06-14 17:58:08 -0700 | [diff] [blame] | 421 |     char prop_value[PROPERTY_VALUE_MAX]; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 422 |  | 
| Mike Lockwood | 782aef1 | 2010-08-10 07:37:50 -0400 | [diff] [blame] | 423 |     MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats(); | 
 | 424 |     MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats(); | 
 | 425 |     MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties(); | 
 | 426 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 427 |     // fill in device info | 
 | 428 |     mData.putUInt16(MTP_STANDARD_VERSION); | 
 | 429 |     mData.putUInt32(6); // MTP Vendor Extension ID | 
 | 430 |     mData.putUInt16(MTP_STANDARD_VERSION); | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 431 |     string.set("microsoft.com: 1.0; android.com: 1.0;"); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 432 |     mData.putString(string); // MTP Extensions | 
 | 433 |     mData.putUInt16(0); //Functional Mode | 
 | 434 |     mData.putAUInt16(kSupportedOperationCodes, | 
 | 435 |             sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported | 
| Mike Lockwood | 873871f | 2010-07-12 18:54:16 -0400 | [diff] [blame] | 436 |     mData.putAUInt16(kSupportedEventCodes, | 
 | 437 |             sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported | 
| Mike Lockwood | 782aef1 | 2010-08-10 07:37:50 -0400 | [diff] [blame] | 438 |     mData.putAUInt16(deviceProperties); // Device Properties Supported | 
 | 439 |     mData.putAUInt16(captureFormats); // Capture Formats | 
 | 440 |     mData.putAUInt16(playbackFormats);  // Playback Formats | 
| Mike Lockwood | 8d08c5a | 2011-01-31 16:44:44 -0500 | [diff] [blame] | 441 |  | 
 | 442 |     property_get("ro.product.manufacturer", prop_value, "unknown manufacturer"); | 
 | 443 |     string.set(prop_value); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 444 |     mData.putString(string);   // Manufacturer | 
| Mike Lockwood | c42aa12 | 2010-06-14 17:58:08 -0700 | [diff] [blame] | 445 |  | 
 | 446 |     property_get("ro.product.model", prop_value, "MTP Device"); | 
 | 447 |     string.set(prop_value); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 448 |     mData.putString(string);   // Model | 
 | 449 |     string.set("1.0"); | 
 | 450 |     mData.putString(string);   // Device Version | 
| Mike Lockwood | c42aa12 | 2010-06-14 17:58:08 -0700 | [diff] [blame] | 451 |  | 
 | 452 |     property_get("ro.serialno", prop_value, "????????"); | 
 | 453 |     string.set(prop_value); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 454 |     mData.putString(string);   // Serial Number | 
 | 455 |  | 
| Mike Lockwood | 782aef1 | 2010-08-10 07:37:50 -0400 | [diff] [blame] | 456 |     delete playbackFormats; | 
 | 457 |     delete captureFormats; | 
 | 458 |     delete deviceProperties; | 
 | 459 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 460 |     return MTP_RESPONSE_OK; | 
 | 461 | } | 
 | 462 |  | 
 | 463 | MtpResponseCode MtpServer::doOpenSession() { | 
 | 464 |     if (mSessionOpen) { | 
 | 465 |         mResponse.setParameter(1, mSessionID); | 
 | 466 |         return MTP_RESPONSE_SESSION_ALREADY_OPEN; | 
 | 467 |     } | 
 | 468 |     mSessionID = mRequest.getParameter(1); | 
 | 469 |     mSessionOpen = true; | 
| Mike Lockwood | 6b3a9d1 | 2010-08-31 16:25:12 -0400 | [diff] [blame] | 470 |  | 
 | 471 |     mDatabase->sessionStarted(); | 
 | 472 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 473 |     return MTP_RESPONSE_OK; | 
 | 474 | } | 
 | 475 |  | 
 | 476 | MtpResponseCode MtpServer::doCloseSession() { | 
 | 477 |     if (!mSessionOpen) | 
 | 478 |         return MTP_RESPONSE_SESSION_NOT_OPEN; | 
 | 479 |     mSessionID = 0; | 
 | 480 |     mSessionOpen = false; | 
| Mike Lockwood | 6b3a9d1 | 2010-08-31 16:25:12 -0400 | [diff] [blame] | 481 |     mDatabase->sessionEnded(); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 482 |     return MTP_RESPONSE_OK; | 
 | 483 | } | 
 | 484 |  | 
 | 485 | MtpResponseCode MtpServer::doGetStorageIDs() { | 
 | 486 |     if (!mSessionOpen) | 
 | 487 |         return MTP_RESPONSE_SESSION_NOT_OPEN; | 
 | 488 |  | 
 | 489 |     int count = mStorages.size(); | 
 | 490 |     mData.putUInt32(count); | 
 | 491 |     for (int i = 0; i < count; i++) | 
 | 492 |         mData.putUInt32(mStorages[i]->getStorageID()); | 
 | 493 |  | 
 | 494 |     return MTP_RESPONSE_OK; | 
 | 495 | } | 
 | 496 |  | 
 | 497 | MtpResponseCode MtpServer::doGetStorageInfo() { | 
 | 498 |     MtpStringBuffer   string; | 
 | 499 |  | 
 | 500 |     if (!mSessionOpen) | 
 | 501 |         return MTP_RESPONSE_SESSION_NOT_OPEN; | 
 | 502 |     MtpStorageID id = mRequest.getParameter(1); | 
 | 503 |     MtpStorage* storage = getStorage(id); | 
 | 504 |     if (!storage) | 
 | 505 |         return MTP_RESPONSE_INVALID_STORAGE_ID; | 
 | 506 |  | 
 | 507 |     mData.putUInt16(storage->getType()); | 
 | 508 |     mData.putUInt16(storage->getFileSystemType()); | 
 | 509 |     mData.putUInt16(storage->getAccessCapability()); | 
 | 510 |     mData.putUInt64(storage->getMaxCapacity()); | 
 | 511 |     mData.putUInt64(storage->getFreeSpace()); | 
 | 512 |     mData.putUInt32(1024*1024*1024); // Free Space in Objects | 
 | 513 |     string.set(storage->getDescription()); | 
 | 514 |     mData.putString(string); | 
 | 515 |     mData.putEmptyString();   // Volume Identifier | 
 | 516 |  | 
 | 517 |     return MTP_RESPONSE_OK; | 
 | 518 | } | 
 | 519 |  | 
 | 520 | MtpResponseCode MtpServer::doGetObjectPropsSupported() { | 
 | 521 |     if (!mSessionOpen) | 
 | 522 |         return MTP_RESPONSE_SESSION_NOT_OPEN; | 
 | 523 |     MtpObjectFormat format = mRequest.getParameter(1); | 
| Mike Lockwood | 2e09e28 | 2010-12-07 10:51:20 -0800 | [diff] [blame] | 524 |     MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format); | 
| Mike Lockwood | 782aef1 | 2010-08-10 07:37:50 -0400 | [diff] [blame] | 525 |     mData.putAUInt16(properties); | 
| Mike Lockwood | bf9b205 | 2010-08-10 15:11:32 -0400 | [diff] [blame] | 526 |     delete properties; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 527 |     return MTP_RESPONSE_OK; | 
 | 528 | } | 
 | 529 |  | 
 | 530 | MtpResponseCode MtpServer::doGetObjectHandles() { | 
 | 531 |     if (!mSessionOpen) | 
 | 532 |         return MTP_RESPONSE_SESSION_NOT_OPEN; | 
 | 533 |     MtpStorageID storageID = mRequest.getParameter(1);      // 0xFFFFFFFF for all storage | 
| Mike Lockwood | e13401b | 2010-05-19 15:12:14 -0400 | [diff] [blame] | 534 |     MtpObjectFormat format = mRequest.getParameter(2);      // 0 for all formats | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 535 |     MtpObjectHandle parent = mRequest.getParameter(3);      // 0xFFFFFFFF for objects with no parent | 
 | 536 |                                                             // 0x00000000 for all objects? | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 537 |  | 
 | 538 |     if (!hasStorage(storageID)) | 
 | 539 |         return MTP_RESPONSE_INVALID_STORAGE_ID; | 
| Mike Lockwood | 1865a5d | 2010-07-03 00:44:05 -0400 | [diff] [blame] | 540 |     if (parent == 0xFFFFFFFF) | 
 | 541 |         parent = 0; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 542 |  | 
 | 543 |     MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent); | 
 | 544 |     mData.putAUInt32(handles); | 
 | 545 |     delete handles; | 
 | 546 |     return MTP_RESPONSE_OK; | 
 | 547 | } | 
 | 548 |  | 
| Mike Lockwood | 343af4e | 2010-08-02 10:52:20 -0400 | [diff] [blame] | 549 | MtpResponseCode MtpServer::doGetNumObjects() { | 
 | 550 |     if (!mSessionOpen) | 
 | 551 |         return MTP_RESPONSE_SESSION_NOT_OPEN; | 
 | 552 |     MtpStorageID storageID = mRequest.getParameter(1);      // 0xFFFFFFFF for all storage | 
 | 553 |     MtpObjectFormat format = mRequest.getParameter(2);      // 0 for all formats | 
 | 554 |     MtpObjectHandle parent = mRequest.getParameter(3);      // 0xFFFFFFFF for objects with no parent | 
 | 555 |                                                             // 0x00000000 for all objects? | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 556 |     if (!hasStorage(storageID)) | 
 | 557 |         return MTP_RESPONSE_INVALID_STORAGE_ID; | 
| Mike Lockwood | 343af4e | 2010-08-02 10:52:20 -0400 | [diff] [blame] | 558 |     if (parent == 0xFFFFFFFF) | 
 | 559 |         parent = 0; | 
 | 560 |  | 
 | 561 |     int count = mDatabase->getNumObjects(storageID, format, parent); | 
 | 562 |     if (count >= 0) { | 
 | 563 |         mResponse.setParameter(1, count); | 
 | 564 |         return MTP_RESPONSE_OK; | 
 | 565 |     } else { | 
 | 566 |         mResponse.setParameter(1, 0); | 
 | 567 |         return MTP_RESPONSE_INVALID_OBJECT_HANDLE; | 
 | 568 |     } | 
 | 569 | } | 
 | 570 |  | 
| Mike Lockwood | 438344f | 2010-08-03 15:30:09 -0400 | [diff] [blame] | 571 | MtpResponseCode MtpServer::doGetObjectReferences() { | 
 | 572 |     if (!mSessionOpen) | 
 | 573 |         return MTP_RESPONSE_SESSION_NOT_OPEN; | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 574 |     if (!hasStorage()) | 
 | 575 |         return MTP_RESPONSE_INVALID_OBJECT_HANDLE; | 
 | 576 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 577 |  | 
 | 578 |     // FIXME - check for invalid object handle | 
| Mike Lockwood | 438344f | 2010-08-03 15:30:09 -0400 | [diff] [blame] | 579 |     MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle); | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 580 |     if (handles) { | 
 | 581 |         mData.putAUInt32(handles); | 
 | 582 |         delete handles; | 
 | 583 |     } else { | 
| Mike Lockwood | 438344f | 2010-08-03 15:30:09 -0400 | [diff] [blame] | 584 |         mData.putEmptyArray(); | 
| Mike Lockwood | 438344f | 2010-08-03 15:30:09 -0400 | [diff] [blame] | 585 |     } | 
| Mike Lockwood | 438344f | 2010-08-03 15:30:09 -0400 | [diff] [blame] | 586 |     return MTP_RESPONSE_OK; | 
 | 587 | } | 
 | 588 |  | 
 | 589 | MtpResponseCode MtpServer::doSetObjectReferences() { | 
 | 590 |     if (!mSessionOpen) | 
 | 591 |         return MTP_RESPONSE_SESSION_NOT_OPEN; | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 592 |     if (!hasStorage()) | 
 | 593 |         return MTP_RESPONSE_INVALID_OBJECT_HANDLE; | 
| Mike Lockwood | 438344f | 2010-08-03 15:30:09 -0400 | [diff] [blame] | 594 |     MtpStorageID handle = mRequest.getParameter(1); | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 595 |  | 
| Mike Lockwood | 438344f | 2010-08-03 15:30:09 -0400 | [diff] [blame] | 596 |     MtpObjectHandleList* references = mData.getAUInt32(); | 
 | 597 |     MtpResponseCode result = mDatabase->setObjectReferences(handle, references); | 
 | 598 |     delete references; | 
 | 599 |     return result; | 
 | 600 | } | 
 | 601 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 602 | MtpResponseCode MtpServer::doGetObjectPropValue() { | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 603 |     if (!hasStorage()) | 
 | 604 |         return MTP_RESPONSE_INVALID_OBJECT_HANDLE; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 605 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
 | 606 |     MtpObjectProperty property = mRequest.getParameter(2); | 
| Mike Lockwood | 59d6ae5 | 2011-01-21 21:00:54 -0800 | [diff] [blame] | 607 |     LOGV("GetObjectPropValue %d %s\n", handle, | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 608 |             MtpDebug::getObjectPropCodeName(property)); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 609 |  | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 610 |     return mDatabase->getObjectPropertyValue(handle, property, mData); | 
 | 611 | } | 
 | 612 |  | 
 | 613 | MtpResponseCode MtpServer::doSetObjectPropValue() { | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 614 |     if (!hasStorage()) | 
 | 615 |         return MTP_RESPONSE_INVALID_OBJECT_HANDLE; | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 616 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
 | 617 |     MtpObjectProperty property = mRequest.getParameter(2); | 
| Mike Lockwood | 59d6ae5 | 2011-01-21 21:00:54 -0800 | [diff] [blame] | 618 |     LOGV("SetObjectPropValue %d %s\n", handle, | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 619 |             MtpDebug::getObjectPropCodeName(property)); | 
 | 620 |  | 
 | 621 |     return mDatabase->setObjectPropertyValue(handle, property, mData); | 
 | 622 | } | 
 | 623 |  | 
 | 624 | MtpResponseCode MtpServer::doGetDevicePropValue() { | 
 | 625 |     MtpDeviceProperty property = mRequest.getParameter(1); | 
| Mike Lockwood | 59d6ae5 | 2011-01-21 21:00:54 -0800 | [diff] [blame] | 626 |     LOGV("GetDevicePropValue %s\n", | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 627 |             MtpDebug::getDevicePropCodeName(property)); | 
 | 628 |  | 
 | 629 |     return mDatabase->getDevicePropertyValue(property, mData); | 
 | 630 | } | 
 | 631 |  | 
 | 632 | MtpResponseCode MtpServer::doSetDevicePropValue() { | 
 | 633 |     MtpDeviceProperty property = mRequest.getParameter(1); | 
| Mike Lockwood | 59d6ae5 | 2011-01-21 21:00:54 -0800 | [diff] [blame] | 634 |     LOGV("SetDevicePropValue %s\n", | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 635 |             MtpDebug::getDevicePropCodeName(property)); | 
 | 636 |  | 
 | 637 |     return mDatabase->setDevicePropertyValue(property, mData); | 
 | 638 | } | 
 | 639 |  | 
 | 640 | MtpResponseCode MtpServer::doResetDevicePropValue() { | 
 | 641 |     MtpDeviceProperty property = mRequest.getParameter(1); | 
| Mike Lockwood | 59d6ae5 | 2011-01-21 21:00:54 -0800 | [diff] [blame] | 642 |     LOGV("ResetDevicePropValue %s\n", | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 643 |             MtpDebug::getDevicePropCodeName(property)); | 
 | 644 |  | 
 | 645 |     return mDatabase->resetDeviceProperty(property); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 646 | } | 
 | 647 |  | 
| Mike Lockwood | b6da06e | 2010-10-14 18:03:25 -0400 | [diff] [blame] | 648 | MtpResponseCode MtpServer::doGetObjectPropList() { | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 649 |     if (!hasStorage()) | 
 | 650 |         return MTP_RESPONSE_INVALID_OBJECT_HANDLE; | 
| Mike Lockwood | b6da06e | 2010-10-14 18:03:25 -0400 | [diff] [blame] | 651 |  | 
 | 652 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
| Mike Lockwood | 40ce1f2 | 2010-12-01 18:46:23 -0500 | [diff] [blame] | 653 |     // use uint32_t so we can support 0xFFFFFFFF | 
 | 654 |     uint32_t format = mRequest.getParameter(2); | 
 | 655 |     uint32_t property = mRequest.getParameter(3); | 
| Mike Lockwood | b6da06e | 2010-10-14 18:03:25 -0400 | [diff] [blame] | 656 |     int groupCode = mRequest.getParameter(4); | 
| Mike Lockwood | f05ff07 | 2010-11-23 18:45:25 -0500 | [diff] [blame] | 657 |     int depth = mRequest.getParameter(5); | 
| Mike Lockwood | 59d6ae5 | 2011-01-21 21:00:54 -0800 | [diff] [blame] | 658 |    LOGV("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n", | 
| Mike Lockwood | b6da06e | 2010-10-14 18:03:25 -0400 | [diff] [blame] | 659 |             handle, MtpDebug::getFormatCodeName(format), | 
 | 660 |             MtpDebug::getObjectPropCodeName(property), groupCode, depth); | 
 | 661 |  | 
 | 662 |     return mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData); | 
 | 663 | } | 
 | 664 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 665 | MtpResponseCode MtpServer::doGetObjectInfo() { | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 666 |     if (!hasStorage()) | 
 | 667 |         return MTP_RESPONSE_INVALID_OBJECT_HANDLE; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 668 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 669 |     MtpObjectInfo info(handle); | 
 | 670 |     MtpResponseCode result = mDatabase->getObjectInfo(handle, info); | 
 | 671 |     if (result == MTP_RESPONSE_OK) { | 
 | 672 |         char    date[20]; | 
 | 673 |  | 
 | 674 |         mData.putUInt32(info.mStorageID); | 
 | 675 |         mData.putUInt16(info.mFormat); | 
 | 676 |         mData.putUInt16(info.mProtectionStatus); | 
 | 677 |  | 
 | 678 |         // if object is being edited the database size may be out of date | 
 | 679 |         uint32_t size = info.mCompressedSize; | 
 | 680 |         ObjectEdit* edit = getEditObject(handle); | 
 | 681 |         if (edit) | 
| Mike Lockwood | c3f16e5 | 2011-04-25 12:56:21 -0700 | [diff] [blame] | 682 |             size = (edit->mSize > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)edit->mSize); | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 683 |         mData.putUInt32(size); | 
 | 684 |  | 
 | 685 |         mData.putUInt16(info.mThumbFormat); | 
 | 686 |         mData.putUInt32(info.mThumbCompressedSize); | 
 | 687 |         mData.putUInt32(info.mThumbPixWidth); | 
 | 688 |         mData.putUInt32(info.mThumbPixHeight); | 
 | 689 |         mData.putUInt32(info.mImagePixWidth); | 
 | 690 |         mData.putUInt32(info.mImagePixHeight); | 
 | 691 |         mData.putUInt32(info.mImagePixDepth); | 
 | 692 |         mData.putUInt32(info.mParent); | 
 | 693 |         mData.putUInt16(info.mAssociationType); | 
 | 694 |         mData.putUInt32(info.mAssociationDesc); | 
 | 695 |         mData.putUInt32(info.mSequenceNumber); | 
 | 696 |         mData.putString(info.mName); | 
 | 697 |         mData.putEmptyString();    // date created | 
 | 698 |         formatDateTime(info.mDateModified, date, sizeof(date)); | 
 | 699 |         mData.putString(date);   // date modified | 
 | 700 |         mData.putEmptyString();   // keywords | 
 | 701 |     } | 
 | 702 |     return result; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 703 | } | 
 | 704 |  | 
 | 705 | MtpResponseCode MtpServer::doGetObject() { | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 706 |     if (!hasStorage()) | 
 | 707 |         return MTP_RESPONSE_INVALID_OBJECT_HANDLE; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 708 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
| Mike Lockwood | c658876 | 2010-06-22 15:03:53 -0400 | [diff] [blame] | 709 |     MtpString pathBuf; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 710 |     int64_t fileLength; | 
| Mike Lockwood | fd34626 | 2010-12-08 16:08:01 -0800 | [diff] [blame] | 711 |     MtpObjectFormat format; | 
 | 712 |     int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); | 
| Mike Lockwood | 9c04c4c | 2010-08-02 10:37:41 -0400 | [diff] [blame] | 713 |     if (result != MTP_RESPONSE_OK) | 
 | 714 |         return result; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 715 |  | 
| Mike Lockwood | 9c04c4c | 2010-08-02 10:37:41 -0400 | [diff] [blame] | 716 |     const char* filePath = (const char *)pathBuf; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 717 |     mtp_file_range  mfr; | 
| Mike Lockwood | c658876 | 2010-06-22 15:03:53 -0400 | [diff] [blame] | 718 |     mfr.fd = open(filePath, O_RDONLY); | 
 | 719 |     if (mfr.fd < 0) { | 
 | 720 |         return MTP_RESPONSE_GENERAL_ERROR; | 
 | 721 |     } | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 722 |     mfr.offset = 0; | 
 | 723 |     mfr.length = fileLength; | 
 | 724 |  | 
 | 725 |     // send data header | 
 | 726 |     mData.setOperationCode(mRequest.getOperationCode()); | 
 | 727 |     mData.setTransactionID(mRequest.getTransactionID()); | 
| Mike Lockwood | 23d2071 | 2010-10-11 17:31:44 -0400 | [diff] [blame] | 728 |     mData.writeDataHeader(mFD, fileLength + MTP_CONTAINER_HEADER_SIZE); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 729 |  | 
 | 730 |     // then transfer the file | 
 | 731 |     int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr); | 
| Mike Lockwood | c658876 | 2010-06-22 15:03:53 -0400 | [diff] [blame] | 732 |     close(mfr.fd); | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 733 |     if (ret < 0) { | 
 | 734 |         if (errno == ECANCELED) | 
 | 735 |             return MTP_RESPONSE_TRANSACTION_CANCELLED; | 
 | 736 |         else | 
 | 737 |             return MTP_RESPONSE_GENERAL_ERROR; | 
 | 738 |     } | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 739 |     return MTP_RESPONSE_OK; | 
 | 740 | } | 
 | 741 |  | 
| Mike Lockwood | 6400078 | 2011-04-24 18:40:17 -0700 | [diff] [blame^] | 742 | MtpResponseCode MtpServer::doGetThumb() { | 
 | 743 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
 | 744 |     size_t thumbSize; | 
 | 745 |     void* thumb = mDatabase->getThumbnail(handle, thumbSize); | 
 | 746 |     if (thumb) { | 
 | 747 |         // send data | 
 | 748 |         mData.setOperationCode(mRequest.getOperationCode()); | 
 | 749 |         mData.setTransactionID(mRequest.getTransactionID()); | 
 | 750 |         mData.writeData(mFD, thumb, thumbSize); | 
 | 751 |         free(thumb); | 
 | 752 |         return MTP_RESPONSE_OK; | 
 | 753 |     } else { | 
 | 754 |         return MTP_RESPONSE_GENERAL_ERROR; | 
 | 755 |     } | 
 | 756 | } | 
 | 757 |  | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 758 | MtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) { | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 759 |     if (!hasStorage()) | 
 | 760 |         return MTP_RESPONSE_INVALID_OBJECT_HANDLE; | 
| Mike Lockwood | d81ce3c | 2010-11-23 09:08:01 -0500 | [diff] [blame] | 761 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 762 |     uint64_t offset; | 
 | 763 |     uint32_t length; | 
 | 764 |     offset = mRequest.getParameter(2); | 
 | 765 |     if (operation == MTP_OPERATION_GET_PARTIAL_OBJECT_64) { | 
 | 766 |         // android extension with 64 bit offset | 
 | 767 |         uint64_t offset2 = mRequest.getParameter(3); | 
 | 768 |         offset = offset | (offset2 << 32); | 
 | 769 |         length = mRequest.getParameter(4); | 
 | 770 |     } else { | 
 | 771 |         // standard GetPartialObject | 
 | 772 |         length = mRequest.getParameter(3); | 
 | 773 |     } | 
| Mike Lockwood | d81ce3c | 2010-11-23 09:08:01 -0500 | [diff] [blame] | 774 |     MtpString pathBuf; | 
 | 775 |     int64_t fileLength; | 
| Mike Lockwood | fd34626 | 2010-12-08 16:08:01 -0800 | [diff] [blame] | 776 |     MtpObjectFormat format; | 
 | 777 |     int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); | 
| Mike Lockwood | d81ce3c | 2010-11-23 09:08:01 -0500 | [diff] [blame] | 778 |     if (result != MTP_RESPONSE_OK) | 
 | 779 |         return result; | 
 | 780 |     if (offset + length > fileLength) | 
 | 781 |         length = fileLength - offset; | 
 | 782 |  | 
 | 783 |     const char* filePath = (const char *)pathBuf; | 
 | 784 |     mtp_file_range  mfr; | 
 | 785 |     mfr.fd = open(filePath, O_RDONLY); | 
 | 786 |     if (mfr.fd < 0) { | 
 | 787 |         return MTP_RESPONSE_GENERAL_ERROR; | 
 | 788 |     } | 
 | 789 |     mfr.offset = offset; | 
 | 790 |     mfr.length = length; | 
 | 791 |     mResponse.setParameter(1, length); | 
 | 792 |  | 
 | 793 |     // send data header | 
 | 794 |     mData.setOperationCode(mRequest.getOperationCode()); | 
 | 795 |     mData.setTransactionID(mRequest.getTransactionID()); | 
 | 796 |     mData.writeDataHeader(mFD, length + MTP_CONTAINER_HEADER_SIZE); | 
 | 797 |  | 
 | 798 |     // then transfer the file | 
 | 799 |     int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr); | 
 | 800 |     close(mfr.fd); | 
 | 801 |     if (ret < 0) { | 
 | 802 |         if (errno == ECANCELED) | 
 | 803 |             return MTP_RESPONSE_TRANSACTION_CANCELLED; | 
 | 804 |         else | 
 | 805 |             return MTP_RESPONSE_GENERAL_ERROR; | 
 | 806 |     } | 
 | 807 |     return MTP_RESPONSE_OK; | 
 | 808 | } | 
 | 809 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 810 | MtpResponseCode MtpServer::doSendObjectInfo() { | 
 | 811 |     MtpString path; | 
 | 812 |     MtpStorageID storageID = mRequest.getParameter(1); | 
 | 813 |     MtpStorage* storage = getStorage(storageID); | 
 | 814 |     MtpObjectHandle parent = mRequest.getParameter(2); | 
 | 815 |     if (!storage) | 
 | 816 |         return MTP_RESPONSE_INVALID_STORAGE_ID; | 
 | 817 |  | 
 | 818 |     // special case the root | 
| Mike Lockwood | 1865a5d | 2010-07-03 00:44:05 -0400 | [diff] [blame] | 819 |     if (parent == MTP_PARENT_ROOT) { | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 820 |         path = storage->getPath(); | 
| Mike Lockwood | 1865a5d | 2010-07-03 00:44:05 -0400 | [diff] [blame] | 821 |         parent = 0; | 
 | 822 |     } else { | 
| Mike Lockwood | fd34626 | 2010-12-08 16:08:01 -0800 | [diff] [blame] | 823 |         int64_t length; | 
 | 824 |         MtpObjectFormat format; | 
 | 825 |         int result = mDatabase->getObjectFilePath(parent, path, length, format); | 
| Mike Lockwood | 9c04c4c | 2010-08-02 10:37:41 -0400 | [diff] [blame] | 826 |         if (result != MTP_RESPONSE_OK) | 
 | 827 |             return result; | 
| Mike Lockwood | fd34626 | 2010-12-08 16:08:01 -0800 | [diff] [blame] | 828 |         if (format != MTP_FORMAT_ASSOCIATION) | 
 | 829 |             return MTP_RESPONSE_INVALID_PARENT_OBJECT; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 830 |     } | 
 | 831 |  | 
 | 832 |     // read only the fields we need | 
 | 833 |     mData.getUInt32();  // storage ID | 
 | 834 |     MtpObjectFormat format = mData.getUInt16(); | 
 | 835 |     mData.getUInt16();  // protection status | 
 | 836 |     mSendObjectFileSize = mData.getUInt32(); | 
 | 837 |     mData.getUInt16();  // thumb format | 
 | 838 |     mData.getUInt32();  // thumb compressed size | 
 | 839 |     mData.getUInt32();  // thumb pix width | 
 | 840 |     mData.getUInt32();  // thumb pix height | 
 | 841 |     mData.getUInt32();  // image pix width | 
 | 842 |     mData.getUInt32();  // image pix height | 
 | 843 |     mData.getUInt32();  // image bit depth | 
 | 844 |     mData.getUInt32();  // parent | 
 | 845 |     uint16_t associationType = mData.getUInt16(); | 
 | 846 |     uint32_t associationDesc = mData.getUInt32();   // association desc | 
 | 847 |     mData.getUInt32();  // sequence number | 
 | 848 |     MtpStringBuffer name, created, modified; | 
 | 849 |     mData.getString(name);    // file name | 
 | 850 |     mData.getString(created);      // date created | 
 | 851 |     mData.getString(modified);     // date modified | 
 | 852 |     // keywords follow | 
 | 853 |  | 
| Mike Lockwood | 59d6ae5 | 2011-01-21 21:00:54 -0800 | [diff] [blame] | 854 |     LOGV("name: %s format: %04X\n", (const char *)name, format); | 
| Mike Lockwood | fceef46 | 2010-05-14 15:35:17 -0400 | [diff] [blame] | 855 |     time_t modifiedTime; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 856 |     if (!parseDateTime(modified, modifiedTime)) | 
 | 857 |         modifiedTime = 0; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 858 |  | 
 | 859 |     if (path[path.size() - 1] != '/') | 
 | 860 |         path += "/"; | 
 | 861 |     path += (const char *)name; | 
 | 862 |  | 
| Mike Lockwood | 20c3be0 | 2010-12-12 12:17:43 -0800 | [diff] [blame] | 863 |     // check space first | 
 | 864 |     if (mSendObjectFileSize > storage->getFreeSpace()) | 
 | 865 |         return MTP_RESPONSE_STORAGE_FULL; | 
 | 866 |  | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 867 | LOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID); | 
| Mike Lockwood | 4714b07 | 2010-07-12 08:49:01 -0400 | [diff] [blame] | 868 |     MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path, | 
 | 869 |             format, parent, storageID, mSendObjectFileSize, modifiedTime); | 
| Mike Lockwood | fceef46 | 2010-05-14 15:35:17 -0400 | [diff] [blame] | 870 |     if (handle == kInvalidObjectHandle) { | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 871 |         return MTP_RESPONSE_GENERAL_ERROR; | 
| Mike Lockwood | fceef46 | 2010-05-14 15:35:17 -0400 | [diff] [blame] | 872 |     } | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 873 |  | 
 | 874 |   if (format == MTP_FORMAT_ASSOCIATION) { | 
 | 875 |         mode_t mask = umask(0); | 
| Mike Lockwood | 8e2a280 | 2010-07-02 15:15:07 -0400 | [diff] [blame] | 876 |         int ret = mkdir((const char *)path, mDirectoryPermission); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 877 |         umask(mask); | 
 | 878 |         if (ret && ret != -EEXIST) | 
 | 879 |             return MTP_RESPONSE_GENERAL_ERROR; | 
| Mike Lockwood | 8e2a280 | 2010-07-02 15:15:07 -0400 | [diff] [blame] | 880 |         chown((const char *)path, getuid(), mFileGroup); | 
| Mike Lockwood | aa95240 | 2011-01-18 11:06:19 -0800 | [diff] [blame] | 881 |  | 
 | 882 |         // SendObject does not get sent for directories, so call endSendObject here instead | 
 | 883 |         mDatabase->endSendObject(path, handle, MTP_FORMAT_ASSOCIATION, MTP_RESPONSE_OK); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 884 |     } else { | 
 | 885 |         mSendObjectFilePath = path; | 
 | 886 |         // save the handle for the SendObject call, which should follow | 
 | 887 |         mSendObjectHandle = handle; | 
| Mike Lockwood | 4714b07 | 2010-07-12 08:49:01 -0400 | [diff] [blame] | 888 |         mSendObjectFormat = format; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 889 |     } | 
 | 890 |  | 
 | 891 |     mResponse.setParameter(1, storageID); | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 892 |     mResponse.setParameter(2, parent); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 893 |     mResponse.setParameter(3, handle); | 
 | 894 |  | 
 | 895 |     return MTP_RESPONSE_OK; | 
 | 896 | } | 
 | 897 |  | 
 | 898 | MtpResponseCode MtpServer::doSendObject() { | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 899 |     if (!hasStorage()) | 
 | 900 |         return MTP_RESPONSE_GENERAL_ERROR; | 
| Mike Lockwood | 4714b07 | 2010-07-12 08:49:01 -0400 | [diff] [blame] | 901 |     MtpResponseCode result = MTP_RESPONSE_OK; | 
 | 902 |     mode_t mask; | 
 | 903 |     int ret; | 
 | 904 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 905 |     if (mSendObjectHandle == kInvalidObjectHandle) { | 
| Mike Lockwood | b14e588 | 2010-06-29 18:11:52 -0400 | [diff] [blame] | 906 |         LOGE("Expected SendObjectInfo before SendObject"); | 
| Mike Lockwood | 4714b07 | 2010-07-12 08:49:01 -0400 | [diff] [blame] | 907 |         result = MTP_RESPONSE_NO_VALID_OBJECT_INFO; | 
 | 908 |         goto done; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 909 |     } | 
 | 910 |  | 
 | 911 |     // read the header | 
| Mike Lockwood | 4714b07 | 2010-07-12 08:49:01 -0400 | [diff] [blame] | 912 |     ret = mData.readDataHeader(mFD); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 913 |     // FIXME - check for errors here. | 
 | 914 |  | 
 | 915 |     // reset so we don't attempt to send this back | 
 | 916 |     mData.reset(); | 
 | 917 |  | 
 | 918 |     mtp_file_range  mfr; | 
| Mike Lockwood | c658876 | 2010-06-22 15:03:53 -0400 | [diff] [blame] | 919 |     mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC); | 
 | 920 |     if (mfr.fd < 0) { | 
| Mike Lockwood | 4714b07 | 2010-07-12 08:49:01 -0400 | [diff] [blame] | 921 |         result = MTP_RESPONSE_GENERAL_ERROR; | 
 | 922 |         goto done; | 
| Mike Lockwood | c658876 | 2010-06-22 15:03:53 -0400 | [diff] [blame] | 923 |     } | 
| Mike Lockwood | 8e2a280 | 2010-07-02 15:15:07 -0400 | [diff] [blame] | 924 |     fchown(mfr.fd, getuid(), mFileGroup); | 
 | 925 |     // set permissions | 
| Mike Lockwood | 4714b07 | 2010-07-12 08:49:01 -0400 | [diff] [blame] | 926 |     mask = umask(0); | 
| Mike Lockwood | 8e2a280 | 2010-07-02 15:15:07 -0400 | [diff] [blame] | 927 |     fchmod(mfr.fd, mFilePermission); | 
 | 928 |     umask(mask); | 
 | 929 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 930 |     mfr.offset = 0; | 
 | 931 |     mfr.length = mSendObjectFileSize; | 
 | 932 |  | 
| Mike Lockwood | 59d6ae5 | 2011-01-21 21:00:54 -0800 | [diff] [blame] | 933 |     LOGV("receiving %s\n", (const char *)mSendObjectFilePath); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 934 |     // transfer the file | 
 | 935 |     ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); | 
| Mike Lockwood | c658876 | 2010-06-22 15:03:53 -0400 | [diff] [blame] | 936 |     close(mfr.fd); | 
| Mike Lockwood | 8e2a280 | 2010-07-02 15:15:07 -0400 | [diff] [blame] | 937 |  | 
| Mike Lockwood | b14e588 | 2010-06-29 18:11:52 -0400 | [diff] [blame] | 938 |     LOGV("MTP_RECEIVE_FILE returned %d", ret); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 939 |  | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 940 |     if (ret < 0) { | 
 | 941 |         unlink(mSendObjectFilePath); | 
 | 942 |         if (errno == ECANCELED) | 
| Mike Lockwood | 4714b07 | 2010-07-12 08:49:01 -0400 | [diff] [blame] | 943 |             result = MTP_RESPONSE_TRANSACTION_CANCELLED; | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 944 |         else | 
| Mike Lockwood | 4714b07 | 2010-07-12 08:49:01 -0400 | [diff] [blame] | 945 |             result = MTP_RESPONSE_GENERAL_ERROR; | 
| Mike Lockwood | 916076c | 2010-06-04 09:49:21 -0400 | [diff] [blame] | 946 |     } | 
| Mike Lockwood | 4714b07 | 2010-07-12 08:49:01 -0400 | [diff] [blame] | 947 |  | 
 | 948 | done: | 
 | 949 |     mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat, | 
| Mike Lockwood | aa95240 | 2011-01-18 11:06:19 -0800 | [diff] [blame] | 950 |             result == MTP_RESPONSE_OK); | 
| Mike Lockwood | 4714b07 | 2010-07-12 08:49:01 -0400 | [diff] [blame] | 951 |     mSendObjectHandle = kInvalidObjectHandle; | 
 | 952 |     mSendObjectFormat = 0; | 
 | 953 |     return result; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 954 | } | 
 | 955 |  | 
| Mike Lockwood | d321149 | 2010-09-13 17:15:58 -0400 | [diff] [blame] | 956 | static void deleteRecursive(const char* path) { | 
 | 957 |     char pathbuf[PATH_MAX]; | 
 | 958 |     int pathLength = strlen(path); | 
 | 959 |     if (pathLength >= sizeof(pathbuf) - 1) { | 
 | 960 |         LOGE("path too long: %s\n", path); | 
 | 961 |     } | 
 | 962 |     strcpy(pathbuf, path); | 
 | 963 |     if (pathbuf[pathLength - 1] != '/') { | 
 | 964 |         pathbuf[pathLength++] = '/'; | 
 | 965 |     } | 
 | 966 |     char* fileSpot = pathbuf + pathLength; | 
 | 967 |     int pathRemaining = sizeof(pathbuf) - pathLength - 1; | 
 | 968 |  | 
 | 969 |     DIR* dir = opendir(path); | 
 | 970 |     if (!dir) { | 
 | 971 |         LOGE("opendir %s failed: %s", path, strerror(errno)); | 
 | 972 |         return; | 
 | 973 |     } | 
 | 974 |  | 
 | 975 |     struct dirent* entry; | 
 | 976 |     while ((entry = readdir(dir))) { | 
 | 977 |         const char* name = entry->d_name; | 
 | 978 |  | 
 | 979 |         // ignore "." and ".." | 
 | 980 |         if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) { | 
 | 981 |             continue; | 
 | 982 |         } | 
 | 983 |  | 
 | 984 |         int nameLength = strlen(name); | 
 | 985 |         if (nameLength > pathRemaining) { | 
 | 986 |             LOGE("path %s/%s too long\n", path, name); | 
 | 987 |             continue; | 
 | 988 |         } | 
 | 989 |         strcpy(fileSpot, name); | 
 | 990 |  | 
 | 991 |         int type = entry->d_type; | 
 | 992 |         if (entry->d_type == DT_DIR) { | 
 | 993 |             deleteRecursive(pathbuf); | 
 | 994 |             rmdir(pathbuf); | 
 | 995 |         } else { | 
 | 996 |             unlink(pathbuf); | 
 | 997 |         } | 
 | 998 |     } | 
| Mike Lockwood | 7ce05cf | 2010-11-11 11:22:32 -0500 | [diff] [blame] | 999 |     closedir(dir); | 
| Mike Lockwood | d321149 | 2010-09-13 17:15:58 -0400 | [diff] [blame] | 1000 | } | 
 | 1001 |  | 
 | 1002 | static void deletePath(const char* path) { | 
 | 1003 |     struct stat statbuf; | 
 | 1004 |     if (stat(path, &statbuf) == 0) { | 
 | 1005 |         if (S_ISDIR(statbuf.st_mode)) { | 
 | 1006 |             deleteRecursive(path); | 
 | 1007 |             rmdir(path); | 
 | 1008 |         } else { | 
 | 1009 |             unlink(path); | 
 | 1010 |         } | 
 | 1011 |     } else { | 
 | 1012 |         LOGE("deletePath stat failed for %s: %s", path, strerror(errno)); | 
 | 1013 |     } | 
 | 1014 | } | 
 | 1015 |  | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 1016 | MtpResponseCode MtpServer::doDeleteObject() { | 
| Mike Lockwood | a849440 | 2011-02-18 09:07:14 -0500 | [diff] [blame] | 1017 |     if (!hasStorage()) | 
 | 1018 |         return MTP_RESPONSE_INVALID_OBJECT_HANDLE; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 1019 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
| Mike Lockwood | d321149 | 2010-09-13 17:15:58 -0400 | [diff] [blame] | 1020 |     MtpObjectFormat format = mRequest.getParameter(2); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 1021 |     // FIXME - support deleting all objects if handle is 0xFFFFFFFF | 
 | 1022 |     // FIXME - implement deleting objects by format | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 1023 |  | 
 | 1024 |     MtpString filePath; | 
 | 1025 |     int64_t fileLength; | 
| Mike Lockwood | fd34626 | 2010-12-08 16:08:01 -0800 | [diff] [blame] | 1026 |     int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format); | 
| Mike Lockwood | 9c04c4c | 2010-08-02 10:37:41 -0400 | [diff] [blame] | 1027 |     if (result == MTP_RESPONSE_OK) { | 
 | 1028 |         LOGV("deleting %s", (const char *)filePath); | 
| Mike Lockwood | d321149 | 2010-09-13 17:15:58 -0400 | [diff] [blame] | 1029 |         deletePath((const char *)filePath); | 
| Mike Lockwood | 9c04c4c | 2010-08-02 10:37:41 -0400 | [diff] [blame] | 1030 |         return mDatabase->deleteFile(handle); | 
 | 1031 |     } else { | 
 | 1032 |         return result; | 
 | 1033 |     } | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 1034 | } | 
 | 1035 |  | 
 | 1036 | MtpResponseCode MtpServer::doGetObjectPropDesc() { | 
| Mike Lockwood | 21ef7d0 | 2010-06-30 17:00:35 -0400 | [diff] [blame] | 1037 |     MtpObjectProperty propCode = mRequest.getParameter(1); | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 1038 |     MtpObjectFormat format = mRequest.getParameter(2); | 
| Mike Lockwood | 59d6ae5 | 2011-01-21 21:00:54 -0800 | [diff] [blame] | 1039 |     LOGV("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode), | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 1040 |                                         MtpDebug::getFormatCodeName(format)); | 
 | 1041 |     MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format); | 
| Mike Lockwood | 21ef7d0 | 2010-06-30 17:00:35 -0400 | [diff] [blame] | 1042 |     if (!property) | 
 | 1043 |         return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED; | 
| Mike Lockwood | 21ef7d0 | 2010-06-30 17:00:35 -0400 | [diff] [blame] | 1044 |     property->write(mData); | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 1045 |     delete property; | 
 | 1046 |     return MTP_RESPONSE_OK; | 
 | 1047 | } | 
 | 1048 |  | 
 | 1049 | MtpResponseCode MtpServer::doGetDevicePropDesc() { | 
 | 1050 |     MtpDeviceProperty propCode = mRequest.getParameter(1); | 
| Mike Lockwood | 59d6ae5 | 2011-01-21 21:00:54 -0800 | [diff] [blame] | 1051 |     LOGV("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode)); | 
| Mike Lockwood | 8277cec | 2010-08-10 15:20:35 -0400 | [diff] [blame] | 1052 |     MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode); | 
 | 1053 |     if (!property) | 
 | 1054 |         return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED; | 
 | 1055 |     property->write(mData); | 
 | 1056 |     delete property; | 
| Mike Lockwood | 21ef7d0 | 2010-06-30 17:00:35 -0400 | [diff] [blame] | 1057 |     return MTP_RESPONSE_OK; | 
| Mike Lockwood | 16864ba | 2010-05-11 17:16:59 -0400 | [diff] [blame] | 1058 | } | 
| Mike Lockwood | 7850ef9 | 2010-05-14 10:10:36 -0400 | [diff] [blame] | 1059 |  | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 1060 | MtpResponseCode MtpServer::doSendPartialObject() { | 
 | 1061 |     if (!hasStorage()) | 
 | 1062 |         return MTP_RESPONSE_INVALID_OBJECT_HANDLE; | 
 | 1063 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
 | 1064 |     uint64_t offset = mRequest.getParameter(2); | 
 | 1065 |     uint64_t offset2 = mRequest.getParameter(3); | 
 | 1066 |     offset = offset | (offset2 << 32); | 
 | 1067 |     uint32_t length = mRequest.getParameter(4); | 
 | 1068 |  | 
 | 1069 |     ObjectEdit* edit = getEditObject(handle); | 
 | 1070 |     if (!edit) { | 
 | 1071 |         LOGE("object not open for edit in doSendPartialObject"); | 
 | 1072 |         return MTP_RESPONSE_GENERAL_ERROR; | 
 | 1073 |     } | 
 | 1074 |  | 
 | 1075 |     // can't start writing past the end of the file | 
| Mike Lockwood | c3f16e5 | 2011-04-25 12:56:21 -0700 | [diff] [blame] | 1076 |     if (offset > edit->mSize) { | 
 | 1077 |         LOGD("writing past end of object, offset: %lld, edit->mSize: %lld", offset, edit->mSize); | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 1078 |         return MTP_RESPONSE_GENERAL_ERROR; | 
 | 1079 |     } | 
 | 1080 |  | 
 | 1081 |     // read the header | 
 | 1082 |     int ret = mData.readDataHeader(mFD); | 
 | 1083 |     // FIXME - check for errors here. | 
 | 1084 |  | 
 | 1085 |     // reset so we don't attempt to send this back | 
 | 1086 |     mData.reset(); | 
 | 1087 |  | 
| Mike Lockwood | c3f16e5 | 2011-04-25 12:56:21 -0700 | [diff] [blame] | 1088 |     const char* filePath = (const char *)edit->mPath; | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 1089 |     LOGV("receiving partial %s %lld %ld\n", filePath, offset, length); | 
 | 1090 |     mtp_file_range  mfr; | 
| Mike Lockwood | c3f16e5 | 2011-04-25 12:56:21 -0700 | [diff] [blame] | 1091 |     mfr.fd = edit->mFD; | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 1092 |     mfr.offset = offset; | 
 | 1093 |     mfr.length = length; | 
 | 1094 |  | 
 | 1095 |     // transfer the file | 
 | 1096 |     ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); | 
 | 1097 |     LOGV("MTP_RECEIVE_FILE returned %d", ret); | 
 | 1098 |     if (ret < 0) { | 
 | 1099 |         mResponse.setParameter(1, 0); | 
 | 1100 |         if (errno == ECANCELED) | 
 | 1101 |             return MTP_RESPONSE_TRANSACTION_CANCELLED; | 
 | 1102 |         else | 
 | 1103 |             return MTP_RESPONSE_GENERAL_ERROR; | 
 | 1104 |     } | 
 | 1105 |     mResponse.setParameter(1, length); | 
 | 1106 |     uint64_t end = offset + length; | 
| Mike Lockwood | c3f16e5 | 2011-04-25 12:56:21 -0700 | [diff] [blame] | 1107 |     if (end > edit->mSize) { | 
 | 1108 |         edit->mSize = end; | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 1109 |     } | 
 | 1110 |     return MTP_RESPONSE_OK; | 
 | 1111 | } | 
 | 1112 |  | 
 | 1113 | MtpResponseCode MtpServer::doTruncateObject() { | 
 | 1114 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
 | 1115 |     ObjectEdit* edit = getEditObject(handle); | 
 | 1116 |     if (!edit) { | 
 | 1117 |         LOGE("object not open for edit in doTruncateObject"); | 
 | 1118 |         return MTP_RESPONSE_GENERAL_ERROR; | 
 | 1119 |     } | 
 | 1120 |  | 
 | 1121 |     uint64_t offset = mRequest.getParameter(2); | 
 | 1122 |     uint64_t offset2 = mRequest.getParameter(3); | 
 | 1123 |     offset |= (offset2 << 32); | 
| Mike Lockwood | c3f16e5 | 2011-04-25 12:56:21 -0700 | [diff] [blame] | 1124 |     if (ftruncate(edit->mFD, offset) != 0) { | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 1125 |         return MTP_RESPONSE_GENERAL_ERROR; | 
 | 1126 |     } else { | 
| Mike Lockwood | c3f16e5 | 2011-04-25 12:56:21 -0700 | [diff] [blame] | 1127 |         edit->mSize = offset; | 
| Mike Lockwood | 7d77dcf | 2011-04-21 17:05:55 -0700 | [diff] [blame] | 1128 |         return MTP_RESPONSE_OK; | 
 | 1129 |     } | 
 | 1130 | } | 
 | 1131 |  | 
 | 1132 | MtpResponseCode MtpServer::doBeginEditObject() { | 
 | 1133 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
 | 1134 |     if (getEditObject(handle)) { | 
 | 1135 |         LOGE("object already open for edit in doBeginEditObject"); | 
 | 1136 |         return MTP_RESPONSE_GENERAL_ERROR; | 
 | 1137 |     } | 
 | 1138 |  | 
 | 1139 |     MtpString path; | 
 | 1140 |     int64_t fileLength; | 
 | 1141 |     MtpObjectFormat format; | 
 | 1142 |     int result = mDatabase->getObjectFilePath(handle, path, fileLength, format); | 
 | 1143 |     if (result != MTP_RESPONSE_OK) | 
 | 1144 |         return result; | 
 | 1145 |  | 
 | 1146 |     int fd = open((const char *)path, O_RDWR | O_EXCL); | 
 | 1147 |     if (fd < 0) { | 
 | 1148 |         LOGE("open failed for %s in doBeginEditObject (%d)", (const char *)path, errno); | 
 | 1149 |         return MTP_RESPONSE_GENERAL_ERROR; | 
 | 1150 |     } | 
 | 1151 |  | 
 | 1152 |     addEditObject(handle, path, fileLength, format, fd); | 
 | 1153 |     return MTP_RESPONSE_OK; | 
 | 1154 | } | 
 | 1155 |  | 
 | 1156 | MtpResponseCode MtpServer::doEndEditObject() { | 
 | 1157 |     MtpObjectHandle handle = mRequest.getParameter(1); | 
 | 1158 |     ObjectEdit* edit = getEditObject(handle); | 
 | 1159 |     if (!edit) { | 
 | 1160 |         LOGE("object not open for edit in doEndEditObject"); | 
 | 1161 |         return MTP_RESPONSE_GENERAL_ERROR; | 
 | 1162 |     } | 
 | 1163 |  | 
 | 1164 |     commitEdit(edit); | 
 | 1165 |     removeEditObject(handle); | 
 | 1166 |     return MTP_RESPONSE_OK; | 
 | 1167 | } | 
 | 1168 |  | 
| Mike Lockwood | 7850ef9 | 2010-05-14 10:10:36 -0400 | [diff] [blame] | 1169 | }  // namespace android |