blob: 0fba4ddf971c72564d8a8996dd62750c210f7aac [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>
24
Mike Lockwoodc42aa122010-06-14 17:58:08 -070025#include <cutils/properties.h>
26
Mike Lockwood16864ba2010-05-11 17:16:59 -040027#include "MtpDebug.h"
28#include "MtpServer.h"
29#include "MtpStorage.h"
30#include "MtpStringBuffer.h"
31#include "MtpDatabase.h"
32
33#include "f_mtp.h"
34
Mike Lockwood7850ef92010-05-14 10:10:36 -040035namespace android {
36
Mike Lockwood16864ba2010-05-11 17:16:59 -040037static const MtpOperationCode kSupportedOperationCodes[] = {
38 MTP_OPERATION_GET_DEVICE_INFO,
39 MTP_OPERATION_OPEN_SESSION,
40 MTP_OPERATION_CLOSE_SESSION,
41 MTP_OPERATION_GET_STORAGE_IDS,
42 MTP_OPERATION_GET_STORAGE_INFO,
43 MTP_OPERATION_GET_NUM_OBJECTS,
44 MTP_OPERATION_GET_OBJECT_HANDLES,
45 MTP_OPERATION_GET_OBJECT_INFO,
46 MTP_OPERATION_GET_OBJECT,
47// MTP_OPERATION_GET_THUMB,
48 MTP_OPERATION_DELETE_OBJECT,
49 MTP_OPERATION_SEND_OBJECT_INFO,
50 MTP_OPERATION_SEND_OBJECT,
51// MTP_OPERATION_INITIATE_CAPTURE,
52// MTP_OPERATION_FORMAT_STORE,
53// MTP_OPERATION_RESET_DEVICE,
54// MTP_OPERATION_SELF_TEST,
55// MTP_OPERATION_SET_OBJECT_PROTECTION,
56// MTP_OPERATION_POWER_DOWN,
57 MTP_OPERATION_GET_DEVICE_PROP_DESC,
58 MTP_OPERATION_GET_DEVICE_PROP_VALUE,
59 MTP_OPERATION_SET_DEVICE_PROP_VALUE,
60 MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
61// MTP_OPERATION_TERMINATE_OPEN_CAPTURE,
62// MTP_OPERATION_MOVE_OBJECT,
63// MTP_OPERATION_COPY_OBJECT,
64// MTP_OPERATION_GET_PARTIAL_OBJECT,
65// MTP_OPERATION_INITIATE_OPEN_CAPTURE,
66 MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED,
67// MTP_OPERATION_GET_OBJECT_PROP_DESC,
68 MTP_OPERATION_GET_OBJECT_PROP_VALUE,
69 MTP_OPERATION_SET_OBJECT_PROP_VALUE,
70// MTP_OPERATION_GET_OBJECT_REFERENCES,
71// MTP_OPERATION_SET_OBJECT_REFERENCES,
72// MTP_OPERATION_SKIP,
73};
74
75static const MtpObjectProperty kSupportedObjectProperties[] = {
76 MTP_PROPERTY_STORAGE_ID,
77 MTP_PROPERTY_OBJECT_FORMAT,
78 MTP_PROPERTY_OBJECT_SIZE,
79 MTP_PROPERTY_OBJECT_FILE_NAME,
80 MTP_PROPERTY_PARENT_OBJECT,
81};
82
83static const MtpObjectFormat kSupportedPlaybackFormats[] = {
Mike Lockwoodfceef462010-05-14 15:35:17 -040084 // MTP_FORMAT_UNDEFINED,
Mike Lockwood16864ba2010-05-11 17:16:59 -040085 MTP_FORMAT_ASSOCIATION,
Mike Lockwoodfceef462010-05-14 15:35:17 -040086 // MTP_FORMAT_TEXT,
87 // MTP_FORMAT_HTML,
Mike Lockwood16864ba2010-05-11 17:16:59 -040088 MTP_FORMAT_MP3,
Mike Lockwoodfceef462010-05-14 15:35:17 -040089 //MTP_FORMAT_AVI,
90 MTP_FORMAT_MPEG,
91 // MTP_FORMAT_ASF,
92 MTP_FORMAT_EXIF_JPEG,
93 MTP_FORMAT_TIFF_EP,
94 // MTP_FORMAT_BMP,
95 MTP_FORMAT_GIF,
96 MTP_FORMAT_JFIF,
97 MTP_FORMAT_PNG,
98 MTP_FORMAT_TIFF,
99 MTP_FORMAT_WMA,
100 MTP_FORMAT_OGG,
101 MTP_FORMAT_AAC,
102 // MTP_FORMAT_FLAC,
103 // MTP_FORMAT_WMV,
104 MTP_FORMAT_MP4_CONTAINER,
105 MTP_FORMAT_MP2,
106 MTP_FORMAT_3GP_CONTAINER,
107 // MTP_FORMAT_ABSTRACT_AUDIO_ALBUM,
108 // MTP_FORMAT_ABSTRACT_AV_PLAYLIST,
109 // MTP_FORMAT_WPL_PLAYLIST,
110 // MTP_FORMAT_M3U_PLAYLIST,
111 // MTP_FORMAT_MPL_PLAYLIST,
112 // MTP_FORMAT_PLS_PLAYLIST,
Mike Lockwood16864ba2010-05-11 17:16:59 -0400113};
114
115MtpServer::MtpServer(int fd, const char* databasePath)
116 : mFD(fd),
117 mDatabasePath(databasePath),
118 mDatabase(NULL),
119 mSessionID(0),
120 mSessionOpen(false),
121 mSendObjectHandle(kInvalidObjectHandle),
122 mSendObjectFileSize(0)
123{
124 mDatabase = new MtpDatabase();
125 mDatabase->open(databasePath, true);
126}
127
128MtpServer::~MtpServer() {
129}
130
131void MtpServer::addStorage(const char* filePath) {
132 int index = mStorages.size() + 1;
133 index |= index << 16; // set high and low part to our index
134 MtpStorage* storage = new MtpStorage(index, filePath, mDatabase);
135 addStorage(storage);
136}
137
138MtpStorage* MtpServer::getStorage(MtpStorageID id) {
139 for (int i = 0; i < mStorages.size(); i++) {
140 MtpStorage* storage = mStorages[i];
141 if (storage->getStorageID() == id)
142 return storage;
143 }
144 return NULL;
145}
146
147void MtpServer::scanStorage() {
148 for (int i = 0; i < mStorages.size(); i++) {
149 MtpStorage* storage = mStorages[i];
150 storage->scanFiles();
151 }
152}
153
154void MtpServer::run() {
155 int fd = mFD;
156
157 printf("MtpServer::run fd: %d\n", fd);
158
159 while (1) {
160 int ret = mRequest.read(fd);
161 if (ret < 0) {
162 fprintf(stderr, "request read returned %d, errno: %d\n", ret, errno);
Mike Lockwood916076c2010-06-04 09:49:21 -0400163 if (errno == ECANCELED) {
164 // return to top of loop and wait for next command
165 continue;
166 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400167 break;
168 }
169 MtpOperationCode operation = mRequest.getOperationCode();
170 MtpTransactionID transaction = mRequest.getTransactionID();
171
172 printf("operation: %s\n", MtpDebug::getOperationCodeName(operation));
173 mRequest.dump();
174
175 // FIXME need to generalize this
176 bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO);
177 if (dataIn) {
178 int ret = mData.read(fd);
179 if (ret < 0) {
180 fprintf(stderr, "data read returned %d, errno: %d\n", ret, errno);
Mike Lockwood916076c2010-06-04 09:49:21 -0400181 if (errno == ECANCELED) {
182 // return to top of loop and wait for next command
183 continue;
184 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400185 break;
186 }
187 printf("received data:\n");
188 mData.dump();
189 } else {
190 mData.reset();
191 }
192
Mike Lockwood916076c2010-06-04 09:49:21 -0400193 if (handleRequest()) {
194 if (!dataIn && mData.hasData()) {
195 mData.setOperationCode(operation);
196 mData.setTransactionID(transaction);
197 printf("sending data:\n");
198 mData.dump();
199 ret = mData.write(fd);
200 if (ret < 0) {
201 fprintf(stderr, "request write returned %d, errno: %d\n", ret, errno);
202 if (errno == ECANCELED) {
203 // return to top of loop and wait for next command
204 continue;
205 }
206 break;
207 }
208 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400209
Mike Lockwood916076c2010-06-04 09:49:21 -0400210 mResponse.setTransactionID(transaction);
211 printf("sending response %04X\n", mResponse.getResponseCode());
212 ret = mResponse.write(fd);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400213 if (ret < 0) {
214 fprintf(stderr, "request write returned %d, errno: %d\n", ret, errno);
Mike Lockwood916076c2010-06-04 09:49:21 -0400215 if (errno == ECANCELED) {
216 // return to top of loop and wait for next command
217 continue;
218 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400219 break;
220 }
Mike Lockwood916076c2010-06-04 09:49:21 -0400221 } else {
222 printf("skipping response\n");
Mike Lockwood16864ba2010-05-11 17:16:59 -0400223 }
224 }
225}
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
235 fprintf(stderr, "expected SendObject after SendObjectInfo\n");
236 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;
261 case MTP_OPERATION_GET_OBJECT_PROP_VALUE:
262 response = doGetObjectPropValue();
263 break;
264 case MTP_OPERATION_GET_OBJECT_INFO:
265 response = doGetObjectInfo();
266 break;
267 case MTP_OPERATION_GET_OBJECT:
268 response = doGetObject();
269 break;
270 case MTP_OPERATION_SEND_OBJECT_INFO:
271 response = doSendObjectInfo();
272 break;
273 case MTP_OPERATION_SEND_OBJECT:
274 response = doSendObject();
275 break;
276 case MTP_OPERATION_DELETE_OBJECT:
277 response = doDeleteObject();
278 break;
279 case MTP_OPERATION_GET_OBJECT_PROP_DESC:
280 default:
281 response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
282 break;
283 }
284
Mike Lockwood916076c2010-06-04 09:49:21 -0400285 if (response == MTP_RESPONSE_TRANSACTION_CANCELLED)
286 return false;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400287 mResponse.setResponseCode(response);
Mike Lockwood916076c2010-06-04 09:49:21 -0400288 return true;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400289}
290
291MtpResponseCode MtpServer::doGetDeviceInfo() {
292 MtpStringBuffer string;
Mike Lockwoodc42aa122010-06-14 17:58:08 -0700293 char prop_value[PROPERTY_VALUE_MAX];
Mike Lockwood16864ba2010-05-11 17:16:59 -0400294
295 // fill in device info
296 mData.putUInt16(MTP_STANDARD_VERSION);
297 mData.putUInt32(6); // MTP Vendor Extension ID
298 mData.putUInt16(MTP_STANDARD_VERSION);
299 string.set("microsoft.com: 1.0;");
300 mData.putString(string); // MTP Extensions
301 mData.putUInt16(0); //Functional Mode
302 mData.putAUInt16(kSupportedOperationCodes,
303 sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported
304 mData.putEmptyArray(); // Events Supported
305 mData.putEmptyArray(); // Device Properties Supported
306 mData.putEmptyArray(); // Capture Formats
307 mData.putAUInt16(kSupportedPlaybackFormats,
308 sizeof(kSupportedPlaybackFormats) / sizeof(uint16_t)); // Playback Formats
309 // FIXME
310 string.set("Google, Inc.");
311 mData.putString(string); // Manufacturer
Mike Lockwoodc42aa122010-06-14 17:58:08 -0700312
313 property_get("ro.product.model", prop_value, "MTP Device");
314 string.set(prop_value);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400315 mData.putString(string); // Model
316 string.set("1.0");
317 mData.putString(string); // Device Version
Mike Lockwoodc42aa122010-06-14 17:58:08 -0700318
319 property_get("ro.serialno", prop_value, "????????");
320 string.set(prop_value);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400321 mData.putString(string); // Serial Number
322
323 return MTP_RESPONSE_OK;
324}
325
326MtpResponseCode MtpServer::doOpenSession() {
327 if (mSessionOpen) {
328 mResponse.setParameter(1, mSessionID);
329 return MTP_RESPONSE_SESSION_ALREADY_OPEN;
330 }
331 mSessionID = mRequest.getParameter(1);
332 mSessionOpen = true;
333 return MTP_RESPONSE_OK;
334}
335
336MtpResponseCode MtpServer::doCloseSession() {
337 if (!mSessionOpen)
338 return MTP_RESPONSE_SESSION_NOT_OPEN;
339 mSessionID = 0;
340 mSessionOpen = false;
341 return MTP_RESPONSE_OK;
342}
343
344MtpResponseCode MtpServer::doGetStorageIDs() {
345 if (!mSessionOpen)
346 return MTP_RESPONSE_SESSION_NOT_OPEN;
347
348 int count = mStorages.size();
349 mData.putUInt32(count);
350 for (int i = 0; i < count; i++)
351 mData.putUInt32(mStorages[i]->getStorageID());
352
353 return MTP_RESPONSE_OK;
354}
355
356MtpResponseCode MtpServer::doGetStorageInfo() {
357 MtpStringBuffer string;
358
359 if (!mSessionOpen)
360 return MTP_RESPONSE_SESSION_NOT_OPEN;
361 MtpStorageID id = mRequest.getParameter(1);
362 MtpStorage* storage = getStorage(id);
363 if (!storage)
364 return MTP_RESPONSE_INVALID_STORAGE_ID;
365
366 mData.putUInt16(storage->getType());
367 mData.putUInt16(storage->getFileSystemType());
368 mData.putUInt16(storage->getAccessCapability());
369 mData.putUInt64(storage->getMaxCapacity());
370 mData.putUInt64(storage->getFreeSpace());
371 mData.putUInt32(1024*1024*1024); // Free Space in Objects
372 string.set(storage->getDescription());
373 mData.putString(string);
374 mData.putEmptyString(); // Volume Identifier
375
376 return MTP_RESPONSE_OK;
377}
378
379MtpResponseCode MtpServer::doGetObjectPropsSupported() {
380 if (!mSessionOpen)
381 return MTP_RESPONSE_SESSION_NOT_OPEN;
382 MtpObjectFormat format = mRequest.getParameter(1);
383 mData.putAUInt16(kSupportedObjectProperties,
384 sizeof(kSupportedObjectProperties) / sizeof(uint16_t));
385 return MTP_RESPONSE_OK;
386}
387
388MtpResponseCode MtpServer::doGetObjectHandles() {
389 if (!mSessionOpen)
390 return MTP_RESPONSE_SESSION_NOT_OPEN;
391 MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
Mike Lockwoode13401b2010-05-19 15:12:14 -0400392 MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
Mike Lockwood16864ba2010-05-11 17:16:59 -0400393 MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
394 // 0x00000000 for all objects?
395
396 MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent);
397 mData.putAUInt32(handles);
398 delete handles;
399 return MTP_RESPONSE_OK;
400}
401
402MtpResponseCode MtpServer::doGetObjectPropValue() {
403 MtpObjectHandle handle = mRequest.getParameter(1);
404 MtpObjectProperty property = mRequest.getParameter(2);
405
406 return mDatabase->getObjectProperty(handle, property, mData);
407}
408
409MtpResponseCode MtpServer::doGetObjectInfo() {
410 MtpObjectHandle handle = mRequest.getParameter(1);
411 return mDatabase->getObjectInfo(handle, mData);
412}
413
414MtpResponseCode MtpServer::doGetObject() {
415 MtpObjectHandle handle = mRequest.getParameter(1);
416 MtpString filePath;
417 int64_t fileLength;
418 if (!mDatabase->getObjectFilePath(handle, filePath, fileLength))
419 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
420
421 mtp_file_range mfr;
422 mfr.path = filePath;
423 mfr.path_length = strlen(mfr.path);
424 mfr.offset = 0;
425 mfr.length = fileLength;
426
427 // send data header
428 mData.setOperationCode(mRequest.getOperationCode());
429 mData.setTransactionID(mRequest.getTransactionID());
430 mData.writeDataHeader(mFD, fileLength);
431
432 // then transfer the file
433 int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr);
Mike Lockwood916076c2010-06-04 09:49:21 -0400434 if (ret < 0) {
435 if (errno == ECANCELED)
436 return MTP_RESPONSE_TRANSACTION_CANCELLED;
437 else
438 return MTP_RESPONSE_GENERAL_ERROR;
439 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400440 return MTP_RESPONSE_OK;
441}
442
443MtpResponseCode MtpServer::doSendObjectInfo() {
444 MtpString path;
445 MtpStorageID storageID = mRequest.getParameter(1);
446 MtpStorage* storage = getStorage(storageID);
447 MtpObjectHandle parent = mRequest.getParameter(2);
448 if (!storage)
449 return MTP_RESPONSE_INVALID_STORAGE_ID;
450
451 // special case the root
452 if (parent == MTP_PARENT_ROOT)
453 path = storage->getPath();
454 else {
455 int64_t dummy;
456 if (!mDatabase->getObjectFilePath(parent, path, dummy))
457 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
458 }
459
460 // read only the fields we need
461 mData.getUInt32(); // storage ID
462 MtpObjectFormat format = mData.getUInt16();
463 mData.getUInt16(); // protection status
464 mSendObjectFileSize = mData.getUInt32();
465 mData.getUInt16(); // thumb format
466 mData.getUInt32(); // thumb compressed size
467 mData.getUInt32(); // thumb pix width
468 mData.getUInt32(); // thumb pix height
469 mData.getUInt32(); // image pix width
470 mData.getUInt32(); // image pix height
471 mData.getUInt32(); // image bit depth
472 mData.getUInt32(); // parent
473 uint16_t associationType = mData.getUInt16();
474 uint32_t associationDesc = mData.getUInt32(); // association desc
475 mData.getUInt32(); // sequence number
476 MtpStringBuffer name, created, modified;
477 mData.getString(name); // file name
478 mData.getString(created); // date created
479 mData.getString(modified); // date modified
480 // keywords follow
481
Mike Lockwoodfceef462010-05-14 15:35:17 -0400482 time_t modifiedTime;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400483 if (!parseDateTime(modified, modifiedTime))
484 modifiedTime = 0;
485printf("SendObjectInfo format: %04X size: %d name: %s, created: %s, modified: %s\n",
486format, mSendObjectFileSize, (const char*)name, (const char*)created, (const char*)modified);
487
488 if (path[path.size() - 1] != '/')
489 path += "/";
490 path += (const char *)name;
491
Mike Lockwoodfceef462010-05-14 15:35:17 -0400492 mDatabase->beginTransaction();
493 MtpObjectHandle handle = mDatabase->addFile((const char*)path, format, parent, storageID,
494 mSendObjectFileSize, modifiedTime);
495 if (handle == kInvalidObjectHandle) {
496 mDatabase->rollbackTransaction();
Mike Lockwood16864ba2010-05-11 17:16:59 -0400497 return MTP_RESPONSE_GENERAL_ERROR;
Mike Lockwoodfceef462010-05-14 15:35:17 -0400498 }
499 uint32_t table = MtpDatabase::getTableForFile(format);
500 if (table == kObjectHandleTableAudio)
501 handle = mDatabase->addAudioFile(handle);
502 mDatabase->commitTransaction();
Mike Lockwood16864ba2010-05-11 17:16:59 -0400503
504 if (format == MTP_FORMAT_ASSOCIATION) {
505 mode_t mask = umask(0);
506 int ret = mkdir((const char *)path, S_IRWXU | S_IRWXG | S_IRWXO);
507 umask(mask);
508 if (ret && ret != -EEXIST)
509 return MTP_RESPONSE_GENERAL_ERROR;
510 } else {
511 mSendObjectFilePath = path;
512 // save the handle for the SendObject call, which should follow
513 mSendObjectHandle = handle;
514 }
515
516 mResponse.setParameter(1, storageID);
517 mResponse.setParameter(2, parent);
518 mResponse.setParameter(3, handle);
519
520 return MTP_RESPONSE_OK;
521}
522
523MtpResponseCode MtpServer::doSendObject() {
524 if (mSendObjectHandle == kInvalidObjectHandle) {
525 fprintf(stderr, "Expected SendObjectInfo before SendObject\n");
526 return MTP_RESPONSE_NO_VALID_OBJECT_INFO;
527 }
528
529 // read the header
530 int ret = mData.readDataHeader(mFD);
531 // FIXME - check for errors here.
532
533 // reset so we don't attempt to send this back
534 mData.reset();
535
536 mtp_file_range mfr;
537 mfr.path = (const char*)mSendObjectFilePath;
538 mfr.path_length = strlen(mfr.path);
539 mfr.offset = 0;
540 mfr.length = mSendObjectFileSize;
541
542 // transfer the file
543 ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
Mike Lockwood916076c2010-06-04 09:49:21 -0400544 // FIXME - we need to delete mSendObjectHandle from the database if this fails.
Mike Lockwood16864ba2010-05-11 17:16:59 -0400545 printf("MTP_RECEIVE_FILE returned %d\n", ret);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400546 mSendObjectHandle = kInvalidObjectHandle;
547
Mike Lockwood916076c2010-06-04 09:49:21 -0400548 if (ret < 0) {
549 unlink(mSendObjectFilePath);
550 if (errno == ECANCELED)
551 return MTP_RESPONSE_TRANSACTION_CANCELLED;
552 else
553 return MTP_RESPONSE_GENERAL_ERROR;
554 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400555 return MTP_RESPONSE_OK;
556}
557
558MtpResponseCode MtpServer::doDeleteObject() {
559 MtpObjectHandle handle = mRequest.getParameter(1);
560 MtpObjectFormat format = mRequest.getParameter(1);
561 // FIXME - support deleting all objects if handle is 0xFFFFFFFF
562 // FIXME - implement deleting objects by format
563 // FIXME - handle non-empty directories
564
565 MtpString filePath;
566 int64_t fileLength;
567 if (!mDatabase->getObjectFilePath(handle, filePath, fileLength))
568 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
569
570printf("deleting %s\n", (const char *)filePath);
571 // one of these should work
572 rmdir((const char *)filePath);
573 unlink((const char *)filePath);
574
575 mDatabase->deleteFile(handle);
576
577 return MTP_RESPONSE_OK;
578}
579
580MtpResponseCode MtpServer::doGetObjectPropDesc() {
581 MtpObjectProperty property = mRequest.getParameter(1);
582 MtpObjectFormat format = mRequest.getParameter(2);
583
584 return -1;
585}
Mike Lockwood7850ef92010-05-14 10:10:36 -0400586
587} // namespace android