blob: 853a5af864f7d153bd4ad13ab8c46217d04db027 [file] [log] [blame]
Mike Lockwood16864ba2010-05-11 17:16:59 -04001/*
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 Lockwoodd3211492010-09-13 17:15:58 -040024#include <sys/stat.h>
25#include <dirent.h>
Mike Lockwood16864ba2010-05-11 17:16:59 -040026
Mike Lockwoodc42aa122010-06-14 17:58:08 -070027#include <cutils/properties.h>
28
Mike Lockwooda881b442010-09-23 22:32:05 -040029#define LOG_TAG "MtpServer"
30
Mike Lockwood16864ba2010-05-11 17:16:59 -040031#include "MtpDebug.h"
Mike Lockwood7f53a192010-07-09 10:45:22 -040032#include "MtpDatabase.h"
Mike Lockwood21ef7d02010-06-30 17:00:35 -040033#include "MtpProperty.h"
Mike Lockwood16864ba2010-05-11 17:16:59 -040034#include "MtpServer.h"
35#include "MtpStorage.h"
36#include "MtpStringBuffer.h"
Mike Lockwood16864ba2010-05-11 17:16:59 -040037
Mike Lockwood8065e202010-07-15 13:36:52 -040038#include <linux/usb/f_mtp.h>
Mike Lockwood16864ba2010-05-11 17:16:59 -040039
Mike Lockwood7850ef92010-05-14 10:10:36 -040040namespace android {
41
Mike Lockwood16864ba2010-05-11 17:16:59 -040042static const MtpOperationCode kSupportedOperationCodes[] = {
43 MTP_OPERATION_GET_DEVICE_INFO,
44 MTP_OPERATION_OPEN_SESSION,
45 MTP_OPERATION_CLOSE_SESSION,
46 MTP_OPERATION_GET_STORAGE_IDS,
47 MTP_OPERATION_GET_STORAGE_INFO,
48 MTP_OPERATION_GET_NUM_OBJECTS,
49 MTP_OPERATION_GET_OBJECT_HANDLES,
50 MTP_OPERATION_GET_OBJECT_INFO,
51 MTP_OPERATION_GET_OBJECT,
52// MTP_OPERATION_GET_THUMB,
53 MTP_OPERATION_DELETE_OBJECT,
54 MTP_OPERATION_SEND_OBJECT_INFO,
55 MTP_OPERATION_SEND_OBJECT,
56// MTP_OPERATION_INITIATE_CAPTURE,
57// MTP_OPERATION_FORMAT_STORE,
58// MTP_OPERATION_RESET_DEVICE,
59// MTP_OPERATION_SELF_TEST,
60// MTP_OPERATION_SET_OBJECT_PROTECTION,
61// MTP_OPERATION_POWER_DOWN,
Mike Lockwoode3e76c42010-09-02 14:57:30 -040062 MTP_OPERATION_GET_DEVICE_PROP_DESC,
Mike Lockwood8277cec2010-08-10 15:20:35 -040063 MTP_OPERATION_GET_DEVICE_PROP_VALUE,
64 MTP_OPERATION_SET_DEVICE_PROP_VALUE,
65 MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
Mike Lockwood16864ba2010-05-11 17:16:59 -040066// MTP_OPERATION_TERMINATE_OPEN_CAPTURE,
67// MTP_OPERATION_MOVE_OBJECT,
68// MTP_OPERATION_COPY_OBJECT,
Mike Lockwoodd81ce3c2010-11-23 09:08:01 -050069 MTP_OPERATION_GET_PARTIAL_OBJECT,
Mike Lockwood16864ba2010-05-11 17:16:59 -040070// MTP_OPERATION_INITIATE_OPEN_CAPTURE,
71 MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED,
Mike Lockwood8277cec2010-08-10 15:20:35 -040072 MTP_OPERATION_GET_OBJECT_PROP_DESC,
Mike Lockwood677f5702010-09-23 23:04:28 -040073 MTP_OPERATION_GET_OBJECT_PROP_VALUE,
74 MTP_OPERATION_SET_OBJECT_PROP_VALUE,
Mike Lockwoodb6da06e2010-10-14 18:03:25 -040075 MTP_OPERATION_GET_OBJECT_PROP_LIST,
76// MTP_OPERATION_SET_OBJECT_PROP_LIST,
77// MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC,
78// MTP_OPERATION_SEND_OBJECT_PROP_LIST,
Mike Lockwood438344f2010-08-03 15:30:09 -040079 MTP_OPERATION_GET_OBJECT_REFERENCES,
80 MTP_OPERATION_SET_OBJECT_REFERENCES,
Mike Lockwood16864ba2010-05-11 17:16:59 -040081// MTP_OPERATION_SKIP,
82};
83
Mike Lockwood873871f2010-07-12 18:54:16 -040084static const MtpEventCode kSupportedEventCodes[] = {
85 MTP_EVENT_OBJECT_ADDED,
86 MTP_EVENT_OBJECT_REMOVED,
87};
88
Mike Lockwood1865a5d2010-07-03 00:44:05 -040089MtpServer::MtpServer(int fd, MtpDatabase* database,
Mike Lockwood8e2a2802010-07-02 15:15:07 -040090 int fileGroup, int filePerm, int directoryPerm)
Mike Lockwood16864ba2010-05-11 17:16:59 -040091 : mFD(fd),
Mike Lockwood1865a5d2010-07-03 00:44:05 -040092 mDatabase(database),
Mike Lockwood8e2a2802010-07-02 15:15:07 -040093 mFileGroup(fileGroup),
94 mFilePermission(filePerm),
95 mDirectoryPermission(directoryPerm),
Mike Lockwood16864ba2010-05-11 17:16:59 -040096 mSessionID(0),
97 mSessionOpen(false),
98 mSendObjectHandle(kInvalidObjectHandle),
Mike Lockwood4714b072010-07-12 08:49:01 -040099 mSendObjectFormat(0),
Mike Lockwood16864ba2010-05-11 17:16:59 -0400100 mSendObjectFileSize(0)
101{
Mike Lockwood16864ba2010-05-11 17:16:59 -0400102}
103
104MtpServer::~MtpServer() {
105}
106
Mike Lockwood20c3be02010-12-12 12:17:43 -0800107void MtpServer::addStorage(const char* filePath, uint64_t reserveSpace) {
Mike Lockwood16864ba2010-05-11 17:16:59 -0400108 int index = mStorages.size() + 1;
109 index |= index << 16; // set high and low part to our index
Mike Lockwood20c3be02010-12-12 12:17:43 -0800110 MtpStorage* storage = new MtpStorage(index, filePath, reserveSpace);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400111 addStorage(storage);
112}
113
114MtpStorage* MtpServer::getStorage(MtpStorageID id) {
Mike Lockwoodfd346262010-12-08 16:08:01 -0800115 if (id == 0)
116 return mStorages[0];
Mike Lockwood16864ba2010-05-11 17:16:59 -0400117 for (int i = 0; i < mStorages.size(); i++) {
Mike Lockwoodfd346262010-12-08 16:08:01 -0800118 MtpStorage* storage = mStorages[i];
Mike Lockwood16864ba2010-05-11 17:16:59 -0400119 if (storage->getStorageID() == id)
120 return storage;
121 }
122 return NULL;
123}
124
Mike Lockwood16864ba2010-05-11 17:16:59 -0400125void MtpServer::run() {
126 int fd = mFD;
127
Mike Lockwood21ef7d02010-06-30 17:00:35 -0400128 LOGV("MtpServer::run fd: %d\n", fd);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400129
130 while (1) {
131 int ret = mRequest.read(fd);
132 if (ret < 0) {
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800133 LOGV("request read returned %d, errno: %d", ret, errno);
Mike Lockwood916076c2010-06-04 09:49:21 -0400134 if (errno == ECANCELED) {
135 // return to top of loop and wait for next command
136 continue;
137 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400138 break;
139 }
140 MtpOperationCode operation = mRequest.getOperationCode();
141 MtpTransactionID transaction = mRequest.getTransactionID();
142
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400143 LOGV("operation: %s", MtpDebug::getOperationCodeName(operation));
Mike Lockwood16864ba2010-05-11 17:16:59 -0400144 mRequest.dump();
145
146 // FIXME need to generalize this
Mike Lockwood438344f2010-08-03 15:30:09 -0400147 bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO
Mike Lockwood8277cec2010-08-10 15:20:35 -0400148 || operation == MTP_OPERATION_SET_OBJECT_REFERENCES
149 || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE
150 || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400151 if (dataIn) {
152 int ret = mData.read(fd);
153 if (ret < 0) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400154 LOGE("data read returned %d, errno: %d", ret, errno);
Mike Lockwood916076c2010-06-04 09:49:21 -0400155 if (errno == ECANCELED) {
156 // return to top of loop and wait for next command
157 continue;
158 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400159 break;
160 }
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400161 LOGV("received data:");
Mike Lockwood16864ba2010-05-11 17:16:59 -0400162 mData.dump();
163 } else {
164 mData.reset();
165 }
166
Mike Lockwood916076c2010-06-04 09:49:21 -0400167 if (handleRequest()) {
168 if (!dataIn && mData.hasData()) {
169 mData.setOperationCode(operation);
170 mData.setTransactionID(transaction);
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400171 LOGV("sending data:");
Mike Lockwood23d20712010-10-11 17:31:44 -0400172 mData.dump();
Mike Lockwood916076c2010-06-04 09:49:21 -0400173 ret = mData.write(fd);
174 if (ret < 0) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400175 LOGE("request write returned %d, errno: %d", ret, errno);
Mike Lockwood916076c2010-06-04 09:49:21 -0400176 if (errno == ECANCELED) {
177 // return to top of loop and wait for next command
178 continue;
179 }
180 break;
181 }
182 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400183
Mike Lockwood916076c2010-06-04 09:49:21 -0400184 mResponse.setTransactionID(transaction);
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400185 LOGV("sending response %04X", mResponse.getResponseCode());
Mike Lockwood916076c2010-06-04 09:49:21 -0400186 ret = mResponse.write(fd);
Mike Lockwood23d20712010-10-11 17:31:44 -0400187 mResponse.dump();
Mike Lockwood16864ba2010-05-11 17:16:59 -0400188 if (ret < 0) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400189 LOGE("request write returned %d, errno: %d", ret, errno);
Mike Lockwood916076c2010-06-04 09:49:21 -0400190 if (errno == ECANCELED) {
191 // return to top of loop and wait for next command
192 continue;
193 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400194 break;
195 }
Mike Lockwood916076c2010-06-04 09:49:21 -0400196 } else {
Mike Lockwood21ef7d02010-06-30 17:00:35 -0400197 LOGV("skipping response\n");
Mike Lockwood16864ba2010-05-11 17:16:59 -0400198 }
199 }
Mike Lockwood6b3a9d12010-08-31 16:25:12 -0400200
201 if (mSessionOpen)
202 mDatabase->sessionEnded();
Mike Lockwood16864ba2010-05-11 17:16:59 -0400203}
204
Mike Lockwood873871f2010-07-12 18:54:16 -0400205void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
Mike Lockwood73ecd232010-07-19 14:29:58 -0400206 if (mSessionOpen) {
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800207 LOGV("sendObjectAdded %d\n", handle);
Mike Lockwood73ecd232010-07-19 14:29:58 -0400208 mEvent.setEventCode(MTP_EVENT_OBJECT_ADDED);
209 mEvent.setTransactionID(mRequest.getTransactionID());
210 mEvent.setParameter(1, handle);
211 int ret = mEvent.write(mFD);
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800212 LOGV("mEvent.write returned %d\n", ret);
Mike Lockwood73ecd232010-07-19 14:29:58 -0400213 }
Mike Lockwood873871f2010-07-12 18:54:16 -0400214}
215
216void MtpServer::sendObjectRemoved(MtpObjectHandle handle) {
Mike Lockwood73ecd232010-07-19 14:29:58 -0400217 if (mSessionOpen) {
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800218 LOGV("sendObjectRemoved %d\n", handle);
Mike Lockwood73ecd232010-07-19 14:29:58 -0400219 mEvent.setEventCode(MTP_EVENT_OBJECT_REMOVED);
220 mEvent.setTransactionID(mRequest.getTransactionID());
221 mEvent.setParameter(1, handle);
222 int ret = mEvent.write(mFD);
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800223 LOGV("mEvent.write returned %d\n", ret);
Mike Lockwood73ecd232010-07-19 14:29:58 -0400224 }
Mike Lockwood873871f2010-07-12 18:54:16 -0400225}
226
Mike Lockwood916076c2010-06-04 09:49:21 -0400227bool MtpServer::handleRequest() {
Mike Lockwood16864ba2010-05-11 17:16:59 -0400228 MtpOperationCode operation = mRequest.getOperationCode();
229 MtpResponseCode response;
230
231 mResponse.reset();
232
233 if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) {
234 // FIXME - need to delete mSendObjectHandle from the database
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400235 LOGE("expected SendObject after SendObjectInfo");
Mike Lockwood16864ba2010-05-11 17:16:59 -0400236 mSendObjectHandle = kInvalidObjectHandle;
237 }
238
239 switch (operation) {
240 case MTP_OPERATION_GET_DEVICE_INFO:
241 response = doGetDeviceInfo();
242 break;
243 case MTP_OPERATION_OPEN_SESSION:
244 response = doOpenSession();
245 break;
246 case MTP_OPERATION_CLOSE_SESSION:
247 response = doCloseSession();
248 break;
249 case MTP_OPERATION_GET_STORAGE_IDS:
250 response = doGetStorageIDs();
251 break;
252 case MTP_OPERATION_GET_STORAGE_INFO:
253 response = doGetStorageInfo();
254 break;
255 case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED:
256 response = doGetObjectPropsSupported();
257 break;
258 case MTP_OPERATION_GET_OBJECT_HANDLES:
259 response = doGetObjectHandles();
260 break;
Mike Lockwood343af4e2010-08-02 10:52:20 -0400261 case MTP_OPERATION_GET_NUM_OBJECTS:
262 response = doGetNumObjects();
263 break;
Mike Lockwood438344f2010-08-03 15:30:09 -0400264 case MTP_OPERATION_GET_OBJECT_REFERENCES:
265 response = doGetObjectReferences();
266 break;
267 case MTP_OPERATION_SET_OBJECT_REFERENCES:
268 response = doSetObjectReferences();
269 break;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400270 case MTP_OPERATION_GET_OBJECT_PROP_VALUE:
271 response = doGetObjectPropValue();
272 break;
Mike Lockwood8277cec2010-08-10 15:20:35 -0400273 case MTP_OPERATION_SET_OBJECT_PROP_VALUE:
274 response = doSetObjectPropValue();
275 break;
276 case MTP_OPERATION_GET_DEVICE_PROP_VALUE:
277 response = doGetDevicePropValue();
278 break;
279 case MTP_OPERATION_SET_DEVICE_PROP_VALUE:
280 response = doSetDevicePropValue();
281 break;
282 case MTP_OPERATION_RESET_DEVICE_PROP_VALUE:
283 response = doResetDevicePropValue();
284 break;
Mike Lockwoodb6da06e2010-10-14 18:03:25 -0400285 case MTP_OPERATION_GET_OBJECT_PROP_LIST:
286 response = doGetObjectPropList();
287 break;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400288 case MTP_OPERATION_GET_OBJECT_INFO:
289 response = doGetObjectInfo();
290 break;
291 case MTP_OPERATION_GET_OBJECT:
292 response = doGetObject();
293 break;
Mike Lockwoodd81ce3c2010-11-23 09:08:01 -0500294 case MTP_OPERATION_GET_PARTIAL_OBJECT:
295 response = doGetPartialObject();
296 break;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400297 case MTP_OPERATION_SEND_OBJECT_INFO:
298 response = doSendObjectInfo();
299 break;
300 case MTP_OPERATION_SEND_OBJECT:
301 response = doSendObject();
302 break;
303 case MTP_OPERATION_DELETE_OBJECT:
304 response = doDeleteObject();
305 break;
306 case MTP_OPERATION_GET_OBJECT_PROP_DESC:
Mike Lockwood21ef7d02010-06-30 17:00:35 -0400307 response = doGetObjectPropDesc();
308 break;
Mike Lockwoode3e76c42010-09-02 14:57:30 -0400309 case MTP_OPERATION_GET_DEVICE_PROP_DESC:
310 response = doGetDevicePropDesc();
311 break;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400312 default:
Mike Lockwooda881b442010-09-23 22:32:05 -0400313 LOGE("got unsupported command %s", MtpDebug::getOperationCodeName(operation));
Mike Lockwood16864ba2010-05-11 17:16:59 -0400314 response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
315 break;
316 }
317
Mike Lockwood916076c2010-06-04 09:49:21 -0400318 if (response == MTP_RESPONSE_TRANSACTION_CANCELLED)
319 return false;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400320 mResponse.setResponseCode(response);
Mike Lockwood916076c2010-06-04 09:49:21 -0400321 return true;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400322}
323
324MtpResponseCode MtpServer::doGetDeviceInfo() {
325 MtpStringBuffer string;
Mike Lockwoodc42aa122010-06-14 17:58:08 -0700326 char prop_value[PROPERTY_VALUE_MAX];
Mike Lockwood16864ba2010-05-11 17:16:59 -0400327
Mike Lockwood782aef12010-08-10 07:37:50 -0400328 MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats();
329 MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats();
330 MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties();
331
Mike Lockwood16864ba2010-05-11 17:16:59 -0400332 // fill in device info
333 mData.putUInt16(MTP_STANDARD_VERSION);
334 mData.putUInt32(6); // MTP Vendor Extension ID
335 mData.putUInt16(MTP_STANDARD_VERSION);
336 string.set("microsoft.com: 1.0;");
337 mData.putString(string); // MTP Extensions
338 mData.putUInt16(0); //Functional Mode
339 mData.putAUInt16(kSupportedOperationCodes,
340 sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported
Mike Lockwood873871f2010-07-12 18:54:16 -0400341 mData.putAUInt16(kSupportedEventCodes,
342 sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported
Mike Lockwood782aef12010-08-10 07:37:50 -0400343 mData.putAUInt16(deviceProperties); // Device Properties Supported
344 mData.putAUInt16(captureFormats); // Capture Formats
345 mData.putAUInt16(playbackFormats); // Playback Formats
Mike Lockwood8d08c5a2011-01-31 16:44:44 -0500346
347 property_get("ro.product.manufacturer", prop_value, "unknown manufacturer");
348 string.set(prop_value);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400349 mData.putString(string); // Manufacturer
Mike Lockwoodc42aa122010-06-14 17:58:08 -0700350
351 property_get("ro.product.model", prop_value, "MTP Device");
352 string.set(prop_value);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400353 mData.putString(string); // Model
354 string.set("1.0");
355 mData.putString(string); // Device Version
Mike Lockwoodc42aa122010-06-14 17:58:08 -0700356
357 property_get("ro.serialno", prop_value, "????????");
358 string.set(prop_value);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400359 mData.putString(string); // Serial Number
360
Mike Lockwood782aef12010-08-10 07:37:50 -0400361 delete playbackFormats;
362 delete captureFormats;
363 delete deviceProperties;
364
Mike Lockwood16864ba2010-05-11 17:16:59 -0400365 return MTP_RESPONSE_OK;
366}
367
368MtpResponseCode MtpServer::doOpenSession() {
369 if (mSessionOpen) {
370 mResponse.setParameter(1, mSessionID);
371 return MTP_RESPONSE_SESSION_ALREADY_OPEN;
372 }
373 mSessionID = mRequest.getParameter(1);
374 mSessionOpen = true;
Mike Lockwood6b3a9d12010-08-31 16:25:12 -0400375
376 mDatabase->sessionStarted();
377
Mike Lockwood16864ba2010-05-11 17:16:59 -0400378 return MTP_RESPONSE_OK;
379}
380
381MtpResponseCode MtpServer::doCloseSession() {
382 if (!mSessionOpen)
383 return MTP_RESPONSE_SESSION_NOT_OPEN;
384 mSessionID = 0;
385 mSessionOpen = false;
Mike Lockwood6b3a9d12010-08-31 16:25:12 -0400386 mDatabase->sessionEnded();
Mike Lockwood16864ba2010-05-11 17:16:59 -0400387 return MTP_RESPONSE_OK;
388}
389
390MtpResponseCode MtpServer::doGetStorageIDs() {
391 if (!mSessionOpen)
392 return MTP_RESPONSE_SESSION_NOT_OPEN;
393
394 int count = mStorages.size();
395 mData.putUInt32(count);
396 for (int i = 0; i < count; i++)
397 mData.putUInt32(mStorages[i]->getStorageID());
398
399 return MTP_RESPONSE_OK;
400}
401
402MtpResponseCode MtpServer::doGetStorageInfo() {
403 MtpStringBuffer string;
404
405 if (!mSessionOpen)
406 return MTP_RESPONSE_SESSION_NOT_OPEN;
407 MtpStorageID id = mRequest.getParameter(1);
408 MtpStorage* storage = getStorage(id);
409 if (!storage)
410 return MTP_RESPONSE_INVALID_STORAGE_ID;
411
412 mData.putUInt16(storage->getType());
413 mData.putUInt16(storage->getFileSystemType());
414 mData.putUInt16(storage->getAccessCapability());
415 mData.putUInt64(storage->getMaxCapacity());
416 mData.putUInt64(storage->getFreeSpace());
417 mData.putUInt32(1024*1024*1024); // Free Space in Objects
418 string.set(storage->getDescription());
419 mData.putString(string);
420 mData.putEmptyString(); // Volume Identifier
421
422 return MTP_RESPONSE_OK;
423}
424
425MtpResponseCode MtpServer::doGetObjectPropsSupported() {
426 if (!mSessionOpen)
427 return MTP_RESPONSE_SESSION_NOT_OPEN;
428 MtpObjectFormat format = mRequest.getParameter(1);
Mike Lockwood2e09e282010-12-07 10:51:20 -0800429 MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format);
Mike Lockwood782aef12010-08-10 07:37:50 -0400430 mData.putAUInt16(properties);
Mike Lockwoodbf9b2052010-08-10 15:11:32 -0400431 delete properties;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400432 return MTP_RESPONSE_OK;
433}
434
435MtpResponseCode MtpServer::doGetObjectHandles() {
436 if (!mSessionOpen)
437 return MTP_RESPONSE_SESSION_NOT_OPEN;
438 MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
Mike Lockwoode13401b2010-05-19 15:12:14 -0400439 MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
Mike Lockwood16864ba2010-05-11 17:16:59 -0400440 MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
441 // 0x00000000 for all objects?
Mike Lockwood1865a5d2010-07-03 00:44:05 -0400442 if (parent == 0xFFFFFFFF)
443 parent = 0;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400444
445 MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent);
446 mData.putAUInt32(handles);
447 delete handles;
448 return MTP_RESPONSE_OK;
449}
450
Mike Lockwood343af4e2010-08-02 10:52:20 -0400451MtpResponseCode MtpServer::doGetNumObjects() {
452 if (!mSessionOpen)
453 return MTP_RESPONSE_SESSION_NOT_OPEN;
454 MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
455 MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
456 MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
457 // 0x00000000 for all objects?
458 if (parent == 0xFFFFFFFF)
459 parent = 0;
460
461 int count = mDatabase->getNumObjects(storageID, format, parent);
462 if (count >= 0) {
463 mResponse.setParameter(1, count);
464 return MTP_RESPONSE_OK;
465 } else {
466 mResponse.setParameter(1, 0);
467 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
468 }
469}
470
Mike Lockwood438344f2010-08-03 15:30:09 -0400471MtpResponseCode MtpServer::doGetObjectReferences() {
472 if (!mSessionOpen)
473 return MTP_RESPONSE_SESSION_NOT_OPEN;
474 MtpStorageID handle = mRequest.getParameter(1);
Mike Lockwood8277cec2010-08-10 15:20:35 -0400475
476 // FIXME - check for invalid object handle
Mike Lockwood438344f2010-08-03 15:30:09 -0400477 MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle);
Mike Lockwood8277cec2010-08-10 15:20:35 -0400478 if (handles) {
479 mData.putAUInt32(handles);
480 delete handles;
481 } else {
Mike Lockwood438344f2010-08-03 15:30:09 -0400482 mData.putEmptyArray();
Mike Lockwood438344f2010-08-03 15:30:09 -0400483 }
Mike Lockwood438344f2010-08-03 15:30:09 -0400484 return MTP_RESPONSE_OK;
485}
486
487MtpResponseCode MtpServer::doSetObjectReferences() {
488 if (!mSessionOpen)
489 return MTP_RESPONSE_SESSION_NOT_OPEN;
490 MtpStorageID handle = mRequest.getParameter(1);
491 MtpObjectHandleList* references = mData.getAUInt32();
492 MtpResponseCode result = mDatabase->setObjectReferences(handle, references);
493 delete references;
494 return result;
495}
496
Mike Lockwood16864ba2010-05-11 17:16:59 -0400497MtpResponseCode MtpServer::doGetObjectPropValue() {
498 MtpObjectHandle handle = mRequest.getParameter(1);
499 MtpObjectProperty property = mRequest.getParameter(2);
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800500 LOGV("GetObjectPropValue %d %s\n", handle,
Mike Lockwood8277cec2010-08-10 15:20:35 -0400501 MtpDebug::getObjectPropCodeName(property));
Mike Lockwood16864ba2010-05-11 17:16:59 -0400502
Mike Lockwood8277cec2010-08-10 15:20:35 -0400503 return mDatabase->getObjectPropertyValue(handle, property, mData);
504}
505
506MtpResponseCode MtpServer::doSetObjectPropValue() {
507 MtpObjectHandle handle = mRequest.getParameter(1);
508 MtpObjectProperty property = mRequest.getParameter(2);
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800509 LOGV("SetObjectPropValue %d %s\n", handle,
Mike Lockwood8277cec2010-08-10 15:20:35 -0400510 MtpDebug::getObjectPropCodeName(property));
511
512 return mDatabase->setObjectPropertyValue(handle, property, mData);
513}
514
515MtpResponseCode MtpServer::doGetDevicePropValue() {
516 MtpDeviceProperty property = mRequest.getParameter(1);
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800517 LOGV("GetDevicePropValue %s\n",
Mike Lockwood8277cec2010-08-10 15:20:35 -0400518 MtpDebug::getDevicePropCodeName(property));
519
520 return mDatabase->getDevicePropertyValue(property, mData);
521}
522
523MtpResponseCode MtpServer::doSetDevicePropValue() {
524 MtpDeviceProperty property = mRequest.getParameter(1);
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800525 LOGV("SetDevicePropValue %s\n",
Mike Lockwood8277cec2010-08-10 15:20:35 -0400526 MtpDebug::getDevicePropCodeName(property));
527
528 return mDatabase->setDevicePropertyValue(property, mData);
529}
530
531MtpResponseCode MtpServer::doResetDevicePropValue() {
532 MtpDeviceProperty property = mRequest.getParameter(1);
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800533 LOGV("ResetDevicePropValue %s\n",
Mike Lockwood8277cec2010-08-10 15:20:35 -0400534 MtpDebug::getDevicePropCodeName(property));
535
536 return mDatabase->resetDeviceProperty(property);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400537}
538
Mike Lockwoodb6da06e2010-10-14 18:03:25 -0400539MtpResponseCode MtpServer::doGetObjectPropList() {
540
541 MtpObjectHandle handle = mRequest.getParameter(1);
Mike Lockwood40ce1f22010-12-01 18:46:23 -0500542 // use uint32_t so we can support 0xFFFFFFFF
543 uint32_t format = mRequest.getParameter(2);
544 uint32_t property = mRequest.getParameter(3);
Mike Lockwoodb6da06e2010-10-14 18:03:25 -0400545 int groupCode = mRequest.getParameter(4);
Mike Lockwoodf05ff072010-11-23 18:45:25 -0500546 int depth = mRequest.getParameter(5);
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800547 LOGV("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n",
Mike Lockwoodb6da06e2010-10-14 18:03:25 -0400548 handle, MtpDebug::getFormatCodeName(format),
549 MtpDebug::getObjectPropCodeName(property), groupCode, depth);
550
551 return mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData);
552}
553
Mike Lockwood16864ba2010-05-11 17:16:59 -0400554MtpResponseCode MtpServer::doGetObjectInfo() {
555 MtpObjectHandle handle = mRequest.getParameter(1);
556 return mDatabase->getObjectInfo(handle, mData);
557}
558
559MtpResponseCode MtpServer::doGetObject() {
560 MtpObjectHandle handle = mRequest.getParameter(1);
Mike Lockwoodc6588762010-06-22 15:03:53 -0400561 MtpString pathBuf;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400562 int64_t fileLength;
Mike Lockwoodfd346262010-12-08 16:08:01 -0800563 MtpObjectFormat format;
564 int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format);
Mike Lockwood9c04c4c2010-08-02 10:37:41 -0400565 if (result != MTP_RESPONSE_OK)
566 return result;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400567
Mike Lockwood9c04c4c2010-08-02 10:37:41 -0400568 const char* filePath = (const char *)pathBuf;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400569 mtp_file_range mfr;
Mike Lockwoodc6588762010-06-22 15:03:53 -0400570 mfr.fd = open(filePath, O_RDONLY);
571 if (mfr.fd < 0) {
572 return MTP_RESPONSE_GENERAL_ERROR;
573 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400574 mfr.offset = 0;
575 mfr.length = fileLength;
576
577 // send data header
578 mData.setOperationCode(mRequest.getOperationCode());
579 mData.setTransactionID(mRequest.getTransactionID());
Mike Lockwood23d20712010-10-11 17:31:44 -0400580 mData.writeDataHeader(mFD, fileLength + MTP_CONTAINER_HEADER_SIZE);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400581
582 // then transfer the file
583 int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr);
Mike Lockwoodc6588762010-06-22 15:03:53 -0400584 close(mfr.fd);
Mike Lockwood916076c2010-06-04 09:49:21 -0400585 if (ret < 0) {
586 if (errno == ECANCELED)
587 return MTP_RESPONSE_TRANSACTION_CANCELLED;
588 else
589 return MTP_RESPONSE_GENERAL_ERROR;
590 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400591 return MTP_RESPONSE_OK;
592}
593
Mike Lockwoodd81ce3c2010-11-23 09:08:01 -0500594MtpResponseCode MtpServer::doGetPartialObject() {
595 MtpObjectHandle handle = mRequest.getParameter(1);
596 uint32_t offset = mRequest.getParameter(2);
597 uint32_t length = mRequest.getParameter(3);
598 MtpString pathBuf;
599 int64_t fileLength;
Mike Lockwoodfd346262010-12-08 16:08:01 -0800600 MtpObjectFormat format;
601 int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format);
Mike Lockwoodd81ce3c2010-11-23 09:08:01 -0500602 if (result != MTP_RESPONSE_OK)
603 return result;
604 if (offset + length > fileLength)
605 length = fileLength - offset;
606
607 const char* filePath = (const char *)pathBuf;
608 mtp_file_range mfr;
609 mfr.fd = open(filePath, O_RDONLY);
610 if (mfr.fd < 0) {
611 return MTP_RESPONSE_GENERAL_ERROR;
612 }
613 mfr.offset = offset;
614 mfr.length = length;
615 mResponse.setParameter(1, length);
616
617 // send data header
618 mData.setOperationCode(mRequest.getOperationCode());
619 mData.setTransactionID(mRequest.getTransactionID());
620 mData.writeDataHeader(mFD, length + MTP_CONTAINER_HEADER_SIZE);
621
622 // then transfer the file
623 int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr);
624 close(mfr.fd);
625 if (ret < 0) {
626 if (errno == ECANCELED)
627 return MTP_RESPONSE_TRANSACTION_CANCELLED;
628 else
629 return MTP_RESPONSE_GENERAL_ERROR;
630 }
631 return MTP_RESPONSE_OK;
632}
633
Mike Lockwood16864ba2010-05-11 17:16:59 -0400634MtpResponseCode MtpServer::doSendObjectInfo() {
635 MtpString path;
636 MtpStorageID storageID = mRequest.getParameter(1);
637 MtpStorage* storage = getStorage(storageID);
638 MtpObjectHandle parent = mRequest.getParameter(2);
639 if (!storage)
640 return MTP_RESPONSE_INVALID_STORAGE_ID;
641
642 // special case the root
Mike Lockwood1865a5d2010-07-03 00:44:05 -0400643 if (parent == MTP_PARENT_ROOT) {
Mike Lockwood16864ba2010-05-11 17:16:59 -0400644 path = storage->getPath();
Mike Lockwood1865a5d2010-07-03 00:44:05 -0400645 parent = 0;
646 } else {
Mike Lockwoodfd346262010-12-08 16:08:01 -0800647 int64_t length;
648 MtpObjectFormat format;
649 int result = mDatabase->getObjectFilePath(parent, path, length, format);
Mike Lockwood9c04c4c2010-08-02 10:37:41 -0400650 if (result != MTP_RESPONSE_OK)
651 return result;
Mike Lockwoodfd346262010-12-08 16:08:01 -0800652 if (format != MTP_FORMAT_ASSOCIATION)
653 return MTP_RESPONSE_INVALID_PARENT_OBJECT;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400654 }
655
656 // read only the fields we need
657 mData.getUInt32(); // storage ID
658 MtpObjectFormat format = mData.getUInt16();
659 mData.getUInt16(); // protection status
660 mSendObjectFileSize = mData.getUInt32();
661 mData.getUInt16(); // thumb format
662 mData.getUInt32(); // thumb compressed size
663 mData.getUInt32(); // thumb pix width
664 mData.getUInt32(); // thumb pix height
665 mData.getUInt32(); // image pix width
666 mData.getUInt32(); // image pix height
667 mData.getUInt32(); // image bit depth
668 mData.getUInt32(); // parent
669 uint16_t associationType = mData.getUInt16();
670 uint32_t associationDesc = mData.getUInt32(); // association desc
671 mData.getUInt32(); // sequence number
672 MtpStringBuffer name, created, modified;
673 mData.getString(name); // file name
674 mData.getString(created); // date created
675 mData.getString(modified); // date modified
676 // keywords follow
677
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800678 LOGV("name: %s format: %04X\n", (const char *)name, format);
Mike Lockwoodfceef462010-05-14 15:35:17 -0400679 time_t modifiedTime;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400680 if (!parseDateTime(modified, modifiedTime))
681 modifiedTime = 0;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400682
683 if (path[path.size() - 1] != '/')
684 path += "/";
685 path += (const char *)name;
686
Mike Lockwood20c3be02010-12-12 12:17:43 -0800687 // check space first
688 if (mSendObjectFileSize > storage->getFreeSpace())
689 return MTP_RESPONSE_STORAGE_FULL;
690
Mike Lockwood4714b072010-07-12 08:49:01 -0400691 MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path,
692 format, parent, storageID, mSendObjectFileSize, modifiedTime);
Mike Lockwoodfceef462010-05-14 15:35:17 -0400693 if (handle == kInvalidObjectHandle) {
Mike Lockwood16864ba2010-05-11 17:16:59 -0400694 return MTP_RESPONSE_GENERAL_ERROR;
Mike Lockwoodfceef462010-05-14 15:35:17 -0400695 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400696
697 if (format == MTP_FORMAT_ASSOCIATION) {
698 mode_t mask = umask(0);
Mike Lockwood8e2a2802010-07-02 15:15:07 -0400699 int ret = mkdir((const char *)path, mDirectoryPermission);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400700 umask(mask);
701 if (ret && ret != -EEXIST)
702 return MTP_RESPONSE_GENERAL_ERROR;
Mike Lockwood8e2a2802010-07-02 15:15:07 -0400703 chown((const char *)path, getuid(), mFileGroup);
Mike Lockwoodaa952402011-01-18 11:06:19 -0800704
705 // SendObject does not get sent for directories, so call endSendObject here instead
706 mDatabase->endSendObject(path, handle, MTP_FORMAT_ASSOCIATION, MTP_RESPONSE_OK);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400707 } else {
708 mSendObjectFilePath = path;
709 // save the handle for the SendObject call, which should follow
710 mSendObjectHandle = handle;
Mike Lockwood4714b072010-07-12 08:49:01 -0400711 mSendObjectFormat = format;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400712 }
713
714 mResponse.setParameter(1, storageID);
Mike Lockwood8277cec2010-08-10 15:20:35 -0400715 mResponse.setParameter(2, parent);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400716 mResponse.setParameter(3, handle);
717
718 return MTP_RESPONSE_OK;
719}
720
721MtpResponseCode MtpServer::doSendObject() {
Mike Lockwood4714b072010-07-12 08:49:01 -0400722 MtpResponseCode result = MTP_RESPONSE_OK;
723 mode_t mask;
724 int ret;
725
Mike Lockwood16864ba2010-05-11 17:16:59 -0400726 if (mSendObjectHandle == kInvalidObjectHandle) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400727 LOGE("Expected SendObjectInfo before SendObject");
Mike Lockwood4714b072010-07-12 08:49:01 -0400728 result = MTP_RESPONSE_NO_VALID_OBJECT_INFO;
729 goto done;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400730 }
731
732 // read the header
Mike Lockwood4714b072010-07-12 08:49:01 -0400733 ret = mData.readDataHeader(mFD);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400734 // FIXME - check for errors here.
735
736 // reset so we don't attempt to send this back
737 mData.reset();
738
739 mtp_file_range mfr;
Mike Lockwoodc6588762010-06-22 15:03:53 -0400740 mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC);
741 if (mfr.fd < 0) {
Mike Lockwood4714b072010-07-12 08:49:01 -0400742 result = MTP_RESPONSE_GENERAL_ERROR;
743 goto done;
Mike Lockwoodc6588762010-06-22 15:03:53 -0400744 }
Mike Lockwood8e2a2802010-07-02 15:15:07 -0400745 fchown(mfr.fd, getuid(), mFileGroup);
746 // set permissions
Mike Lockwood4714b072010-07-12 08:49:01 -0400747 mask = umask(0);
Mike Lockwood8e2a2802010-07-02 15:15:07 -0400748 fchmod(mfr.fd, mFilePermission);
749 umask(mask);
750
Mike Lockwood16864ba2010-05-11 17:16:59 -0400751 mfr.offset = 0;
752 mfr.length = mSendObjectFileSize;
753
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800754 LOGV("receiving %s\n", (const char *)mSendObjectFilePath);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400755 // transfer the file
756 ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
Mike Lockwoodc6588762010-06-22 15:03:53 -0400757 close(mfr.fd);
Mike Lockwood8e2a2802010-07-02 15:15:07 -0400758
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400759 LOGV("MTP_RECEIVE_FILE returned %d", ret);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400760
Mike Lockwood916076c2010-06-04 09:49:21 -0400761 if (ret < 0) {
762 unlink(mSendObjectFilePath);
763 if (errno == ECANCELED)
Mike Lockwood4714b072010-07-12 08:49:01 -0400764 result = MTP_RESPONSE_TRANSACTION_CANCELLED;
Mike Lockwood916076c2010-06-04 09:49:21 -0400765 else
Mike Lockwood4714b072010-07-12 08:49:01 -0400766 result = MTP_RESPONSE_GENERAL_ERROR;
Mike Lockwood916076c2010-06-04 09:49:21 -0400767 }
Mike Lockwood4714b072010-07-12 08:49:01 -0400768
769done:
770 mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat,
Mike Lockwoodaa952402011-01-18 11:06:19 -0800771 result == MTP_RESPONSE_OK);
Mike Lockwood4714b072010-07-12 08:49:01 -0400772 mSendObjectHandle = kInvalidObjectHandle;
773 mSendObjectFormat = 0;
774 return result;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400775}
776
Mike Lockwoodd3211492010-09-13 17:15:58 -0400777static void deleteRecursive(const char* path) {
778 char pathbuf[PATH_MAX];
779 int pathLength = strlen(path);
780 if (pathLength >= sizeof(pathbuf) - 1) {
781 LOGE("path too long: %s\n", path);
782 }
783 strcpy(pathbuf, path);
784 if (pathbuf[pathLength - 1] != '/') {
785 pathbuf[pathLength++] = '/';
786 }
787 char* fileSpot = pathbuf + pathLength;
788 int pathRemaining = sizeof(pathbuf) - pathLength - 1;
789
790 DIR* dir = opendir(path);
791 if (!dir) {
792 LOGE("opendir %s failed: %s", path, strerror(errno));
793 return;
794 }
795
796 struct dirent* entry;
797 while ((entry = readdir(dir))) {
798 const char* name = entry->d_name;
799
800 // ignore "." and ".."
801 if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
802 continue;
803 }
804
805 int nameLength = strlen(name);
806 if (nameLength > pathRemaining) {
807 LOGE("path %s/%s too long\n", path, name);
808 continue;
809 }
810 strcpy(fileSpot, name);
811
812 int type = entry->d_type;
813 if (entry->d_type == DT_DIR) {
814 deleteRecursive(pathbuf);
815 rmdir(pathbuf);
816 } else {
817 unlink(pathbuf);
818 }
819 }
Mike Lockwood7ce05cf2010-11-11 11:22:32 -0500820 closedir(dir);
Mike Lockwoodd3211492010-09-13 17:15:58 -0400821}
822
823static void deletePath(const char* path) {
824 struct stat statbuf;
825 if (stat(path, &statbuf) == 0) {
826 if (S_ISDIR(statbuf.st_mode)) {
827 deleteRecursive(path);
828 rmdir(path);
829 } else {
830 unlink(path);
831 }
832 } else {
833 LOGE("deletePath stat failed for %s: %s", path, strerror(errno));
834 }
835}
836
Mike Lockwood16864ba2010-05-11 17:16:59 -0400837MtpResponseCode MtpServer::doDeleteObject() {
838 MtpObjectHandle handle = mRequest.getParameter(1);
Mike Lockwoodd3211492010-09-13 17:15:58 -0400839 MtpObjectFormat format = mRequest.getParameter(2);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400840 // FIXME - support deleting all objects if handle is 0xFFFFFFFF
841 // FIXME - implement deleting objects by format
Mike Lockwood16864ba2010-05-11 17:16:59 -0400842
843 MtpString filePath;
844 int64_t fileLength;
Mike Lockwoodfd346262010-12-08 16:08:01 -0800845 int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format);
Mike Lockwood9c04c4c2010-08-02 10:37:41 -0400846 if (result == MTP_RESPONSE_OK) {
847 LOGV("deleting %s", (const char *)filePath);
Mike Lockwoodd3211492010-09-13 17:15:58 -0400848 deletePath((const char *)filePath);
Mike Lockwood9c04c4c2010-08-02 10:37:41 -0400849 return mDatabase->deleteFile(handle);
850 } else {
851 return result;
852 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400853}
854
855MtpResponseCode MtpServer::doGetObjectPropDesc() {
Mike Lockwood21ef7d02010-06-30 17:00:35 -0400856 MtpObjectProperty propCode = mRequest.getParameter(1);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400857 MtpObjectFormat format = mRequest.getParameter(2);
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800858 LOGV("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode),
Mike Lockwood8277cec2010-08-10 15:20:35 -0400859 MtpDebug::getFormatCodeName(format));
860 MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format);
Mike Lockwood21ef7d02010-06-30 17:00:35 -0400861 if (!property)
862 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
Mike Lockwood21ef7d02010-06-30 17:00:35 -0400863 property->write(mData);
Mike Lockwood8277cec2010-08-10 15:20:35 -0400864 delete property;
865 return MTP_RESPONSE_OK;
866}
867
868MtpResponseCode MtpServer::doGetDevicePropDesc() {
869 MtpDeviceProperty propCode = mRequest.getParameter(1);
Mike Lockwood59d6ae52011-01-21 21:00:54 -0800870 LOGV("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode));
Mike Lockwood8277cec2010-08-10 15:20:35 -0400871 MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode);
872 if (!property)
873 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
874 property->write(mData);
875 delete property;
Mike Lockwood21ef7d02010-06-30 17:00:35 -0400876 return MTP_RESPONSE_OK;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400877}
Mike Lockwood7850ef92010-05-14 10:10:36 -0400878
879} // namespace android