blob: 17053f1de2aa561669783853f0d0366a3cc71c5f [file] [log] [blame]
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -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 * Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
17 */
18
19#include <utils/Log.h>
20
21#include <stdio.h>
22#include <assert.h>
23#include <limits.h>
24#include <unistd.h>
25#include <fcntl.h>
26#include <dirent.h>
27#include <errno.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <string>
31#include <map>
32#include <libgen.h>
33#include <cutils/properties.h>
34
35#include "MtpDatabase.h"
36#include "MtpStorage.h"
37#include "MtpDataPacket.h"
38#include "MtpObjectInfo.h"
39#include "MtpProperty.h"
40#include "MtpDebug.h"
41#include "MtpStringBuffer.h"
42#include "MtpUtils.h"
43#include "mtp.h"
44#include "mtp_MtpDatabase.hpp"
that9e0593e2014-10-08 00:01:24 +020045//#include "btree.hpp"
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -040046
47MyMtpDatabase::MyMtpDatabase()
48{
49 storagenum = 0;
50 count = -1;
51}
52
53MyMtpDatabase::~MyMtpDatabase() {
54 std::map<int, MtpStorage*>::iterator i;
55 for (i = storagemap.begin(); i != storagemap.end(); i++) {
56 delete i->second;
57 }
58}
59
bigbiff bigbiff1812c892014-09-08 21:04:06 -040060int MyMtpDatabase::DEVICE_PROPERTIES[3] = {
61 MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
62 MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
63 MTP_DEVICE_PROPERTY_IMAGE_SIZE
64};
65
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -040066int MyMtpDatabase::FILE_PROPERTIES[10] = {
67 // NOTE must match beginning of AUDIO_PROPERTIES, VIDEO_PROPERTIES
68 // and IMAGE_PROPERTIES below
69 MTP_PROPERTY_STORAGE_ID,
70 MTP_PROPERTY_OBJECT_FORMAT,
71 MTP_PROPERTY_PROTECTION_STATUS,
72 MTP_PROPERTY_OBJECT_SIZE,
73 MTP_PROPERTY_OBJECT_FILE_NAME,
74 MTP_PROPERTY_DATE_MODIFIED,
75 MTP_PROPERTY_PARENT_OBJECT,
76 MTP_PROPERTY_PERSISTENT_UID,
77 MTP_PROPERTY_NAME,
that9e0593e2014-10-08 00:01:24 +020078 // TODO: why is DISPLAY_NAME not here?
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -040079 MTP_PROPERTY_DATE_ADDED
80};
bigbiff bigbiff1812c892014-09-08 21:04:06 -040081
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -040082int MyMtpDatabase::AUDIO_PROPERTIES[19] = {
83 // NOTE must match FILE_PROPERTIES above
84 MTP_PROPERTY_STORAGE_ID,
85 MTP_PROPERTY_OBJECT_FORMAT,
86 MTP_PROPERTY_PROTECTION_STATUS,
87 MTP_PROPERTY_OBJECT_SIZE,
88 MTP_PROPERTY_OBJECT_FILE_NAME,
89 MTP_PROPERTY_DATE_MODIFIED,
90 MTP_PROPERTY_PARENT_OBJECT,
91 MTP_PROPERTY_PERSISTENT_UID,
92 MTP_PROPERTY_NAME,
93 MTP_PROPERTY_DISPLAY_NAME,
94 MTP_PROPERTY_DATE_ADDED,
95
96 // audio specific properties
97 MTP_PROPERTY_ARTIST,
98 MTP_PROPERTY_ALBUM_NAME,
99 MTP_PROPERTY_ALBUM_ARTIST,
100 MTP_PROPERTY_TRACK,
101 MTP_PROPERTY_ORIGINAL_RELEASE_DATE,
102 MTP_PROPERTY_DURATION,
103 MTP_PROPERTY_GENRE,
104 MTP_PROPERTY_COMPOSER
105};
106
107int MyMtpDatabase::VIDEO_PROPERTIES[15] = {
108 // NOTE must match FILE_PROPERTIES above
109 MTP_PROPERTY_STORAGE_ID,
110 MTP_PROPERTY_OBJECT_FORMAT,
111 MTP_PROPERTY_PROTECTION_STATUS,
112 MTP_PROPERTY_OBJECT_SIZE,
113 MTP_PROPERTY_OBJECT_FILE_NAME,
114 MTP_PROPERTY_DATE_MODIFIED,
115 MTP_PROPERTY_PARENT_OBJECT,
116 MTP_PROPERTY_PERSISTENT_UID,
117 MTP_PROPERTY_NAME,
118 MTP_PROPERTY_DISPLAY_NAME,
119 MTP_PROPERTY_DATE_ADDED,
120
121 // video specific properties
122 MTP_PROPERTY_ARTIST,
123 MTP_PROPERTY_ALBUM_NAME,
124 MTP_PROPERTY_DURATION,
125 MTP_PROPERTY_DESCRIPTION
126};
127
128int MyMtpDatabase::IMAGE_PROPERTIES[12] = {
129 // NOTE must match FILE_PROPERTIES above
130 MTP_PROPERTY_STORAGE_ID,
131 MTP_PROPERTY_OBJECT_FORMAT,
132 MTP_PROPERTY_PROTECTION_STATUS,
133 MTP_PROPERTY_OBJECT_SIZE,
134 MTP_PROPERTY_OBJECT_FILE_NAME,
135 MTP_PROPERTY_DATE_MODIFIED,
136 MTP_PROPERTY_PARENT_OBJECT,
137 MTP_PROPERTY_PERSISTENT_UID,
138 MTP_PROPERTY_NAME,
139 MTP_PROPERTY_DISPLAY_NAME,
140 MTP_PROPERTY_DATE_ADDED,
141
142 // image specific properties
143 MTP_PROPERTY_DESCRIPTION
144};
145
146int MyMtpDatabase::ALL_PROPERTIES[25] = {
147 // NOTE must match FILE_PROPERTIES above
148 MTP_PROPERTY_STORAGE_ID,
149 MTP_PROPERTY_OBJECT_FORMAT,
150 MTP_PROPERTY_PROTECTION_STATUS,
151 MTP_PROPERTY_OBJECT_SIZE,
152 MTP_PROPERTY_OBJECT_FILE_NAME,
153 MTP_PROPERTY_DATE_MODIFIED,
154 MTP_PROPERTY_PARENT_OBJECT,
155 MTP_PROPERTY_PERSISTENT_UID,
156 MTP_PROPERTY_NAME,
157 MTP_PROPERTY_DISPLAY_NAME,
158 MTP_PROPERTY_DATE_ADDED,
159
160 // image specific properties
161 MTP_PROPERTY_DESCRIPTION,
162
163 // audio specific properties
164 MTP_PROPERTY_ARTIST,
165 MTP_PROPERTY_ALBUM_NAME,
166 MTP_PROPERTY_ALBUM_ARTIST,
167 MTP_PROPERTY_TRACK,
168 MTP_PROPERTY_ORIGINAL_RELEASE_DATE,
169 MTP_PROPERTY_DURATION,
170 MTP_PROPERTY_GENRE,
171 MTP_PROPERTY_COMPOSER,
172
173 // video specific properties
174 MTP_PROPERTY_ARTIST,
175 MTP_PROPERTY_ALBUM_NAME,
176 MTP_PROPERTY_DURATION,
177 MTP_PROPERTY_DESCRIPTION,
178
179 // image specific properties
180 MTP_PROPERTY_DESCRIPTION
181};
182
183int MyMtpDatabase::SUPPORTED_PLAYBACK_FORMATS[26] = {
184 SUPPORTED_PLAYBACK_FORMAT_UNDEFINED,
185 SUPPORTED_PLAYBACK_FORMAT_ASSOCIATION,
186 SUPPORTED_PLAYBACK_FORMAT_TEXT,
187 SUPPORTED_PLAYBACK_FORMAT_HTML,
188 SUPPORTED_PLAYBACK_FORMAT_WAV,
189 SUPPORTED_PLAYBACK_FORMAT_MP3,
190 SUPPORTED_PLAYBACK_FORMAT_MPEG,
191 SUPPORTED_PLAYBACK_FORMAT_EXIF_JPEG,
192 SUPPORTED_PLAYBACK_FORMAT_TIFF_EP,
193 SUPPORTED_PLAYBACK_FORMAT_BMP,
194 SUPPORTED_PLAYBACK_FORMAT_GIF,
195 SUPPORTED_PLAYBACK_FORMAT_JFIF,
196 SUPPORTED_PLAYBACK_FORMAT_PNG,
197 SUPPORTED_PLAYBACK_FORMAT_TIFF,
198 SUPPORTED_PLAYBACK_FORMAT_WMA,
199 SUPPORTED_PLAYBACK_FORMAT_OGG,
200 SUPPORTED_PLAYBACK_FORMAT_AAC,
201 SUPPORTED_PLAYBACK_FORMAT_MP4_CONTAINER,
202 SUPPORTED_PLAYBACK_FORMAT_MP2,
203 SUPPORTED_PLAYBACK_FORMAT_3GP_CONTAINER,
204 SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_AV_PLAYLIST,
205 SUPPORTED_PLAYBACK_FORMAT_WPL_PLAYLIST,
206 SUPPORTED_PLAYBACK_FORMAT_M3U_PLAYLIST,
207 SUPPORTED_PLAYBACK_FORMAT_PLS_PLAYLIST,
208 SUPPORTED_PLAYBACK_FORMAT_XML_DOCUMENT,
209 SUPPORTED_PLAYBACK_FORMAT_FLAC
210};
211
212MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
213 MtpObjectFormat format,
214 MtpObjectHandle parent,
215 MtpStorageID storage,
216 uint64_t size,
217 time_t modified) {
that9e0593e2014-10-08 00:01:24 +0200218 if (storagemap.find(storage) == storagemap.end())
219 return kInvalidObjectHandle;
220 return storagemap[storage]->beginSendObject(path, format, parent, size, modified);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400221}
222
223void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
224 MtpObjectFormat format, bool succeeded) {
225 MTPD("endSendObject() %s\n", path);
226 if (!succeeded) {
227 MTPE("endSendObject() failed, unlinking %s\n", path);
228 unlink(path);
229 }
that9e0593e2014-10-08 00:01:24 +0200230 std::map<int, MtpStorage*>::iterator storit;
231 for (storit = storagemap.begin(); storit != storagemap.end(); storit++)
232 storit->second->endSendObject(path, handle, format, succeeded);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400233}
234
235void MyMtpDatabase::createDB(MtpStorage* storage, MtpStorageID storageID) {
Ethan Yonker726a0202014-12-16 20:01:38 -0600236 MTPD("MyMtpDatabase::createDB called\n");
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400237 storagemap[storageID] = storage;
238 storage->createDB();
239}
240
Ethan Yonker726a0202014-12-16 20:01:38 -0600241void MyMtpDatabase::destroyDB(MtpStorageID storageID) {
242 MtpStorage* storage = storagemap[storageID];
243 storagemap.erase(storageID);
244 delete storage;
245}
246
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400247MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
248 MtpObjectFormat format,
249 MtpObjectHandle parent) {
250 MTPD("storageID: %d\n", storageID);
that9e0593e2014-10-08 00:01:24 +0200251 MtpObjectHandleList* list = storagemap[storageID]->getObjectList(storageID, parent);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400252 MTPD("list: %d\n", list->size());
253 return list;
254}
255
256int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
257 MtpObjectFormat format,
258 MtpObjectHandle parent) {
that9e0593e2014-10-08 00:01:24 +0200259 MtpObjectHandleList* list = storagemap[storageID]->getObjectList(storageID, parent);
260 int size = list->size();
261 delete list;
262 return size;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400263}
264
265MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
266 // This function tells the host PC which file formats the device supports
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400267 MtpObjectFormatList* list = new MtpObjectFormatList();
that9e0593e2014-10-08 00:01:24 +0200268 int length = sizeof(SUPPORTED_PLAYBACK_FORMATS) / sizeof(SUPPORTED_PLAYBACK_FORMATS[0]);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400269 MTPD("MyMtpDatabase::getSupportedPlaybackFormats length: %i\n", length);
270 for (int i = 0; i < length; i++) {
that9e0593e2014-10-08 00:01:24 +0200271 MTPD("supported playback format: %x\n", SUPPORTED_PLAYBACK_FORMATS[i]);
272 list->push(SUPPORTED_PLAYBACK_FORMATS[i]);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400273 }
274 return list;
275}
276
277MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
278 // Android OS implementation of this function returns NULL
279 // so we are not implementing this function either.
280 MTPD("MyMtpDatabase::getSupportedCaptureFormats returning NULL (This is what Android does as well).\n");
281 return NULL;
282}
283
284MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
285 int* properties;
286 MtpObjectPropertyList* list = new MtpObjectPropertyList();
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400287 int length = 0;
288 switch (format) {
289 case MTP_FORMAT_MP3:
290 case MTP_FORMAT_WAV:
291 case MTP_FORMAT_WMA:
292 case MTP_FORMAT_OGG:
293 case MTP_FORMAT_AAC:
294 properties = AUDIO_PROPERTIES;
295 length = sizeof(AUDIO_PROPERTIES) / sizeof(AUDIO_PROPERTIES[0]);
that9e0593e2014-10-08 00:01:24 +0200296 break;
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400297 case MTP_FORMAT_MPEG:
298 case MTP_FORMAT_3GP_CONTAINER:
299 case MTP_FORMAT_WMV:
300 properties = VIDEO_PROPERTIES;
301 length = sizeof(VIDEO_PROPERTIES) / sizeof(VIDEO_PROPERTIES[0]);
that9e0593e2014-10-08 00:01:24 +0200302 break;
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400303 case MTP_FORMAT_EXIF_JPEG:
304 case MTP_FORMAT_GIF:
305 case MTP_FORMAT_PNG:
306 case MTP_FORMAT_BMP:
307 properties = IMAGE_PROPERTIES;
308 length = sizeof(IMAGE_PROPERTIES) / sizeof(IMAGE_PROPERTIES[0]);
that9e0593e2014-10-08 00:01:24 +0200309 break;
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400310 case 0:
311 properties = ALL_PROPERTIES;
312 length = sizeof(ALL_PROPERTIES) / sizeof(ALL_PROPERTIES[0]);
that9e0593e2014-10-08 00:01:24 +0200313 break;
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400314 default:
315 properties = FILE_PROPERTIES;
316 length = sizeof(FILE_PROPERTIES) / sizeof(FILE_PROPERTIES[0]);
317 }
that9e0593e2014-10-08 00:01:24 +0200318 MTPD("MyMtpDatabase::getSupportedObjectProperties length is: %i, format: %x", length, format);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400319 for (int i = 0; i < length; i++) {
320 MTPD("supported object property: %x\n", properties[i]);
321 list->push(properties[i]);
322 }
323 return list;
324}
325
326MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400327 MtpDevicePropertyList* list = new MtpDevicePropertyList();
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400328 int length = sizeof(DEVICE_PROPERTIES) / sizeof(DEVICE_PROPERTIES[0]);
that9e0593e2014-10-08 00:01:24 +0200329 MTPD("MyMtpDatabase::getSupportedDeviceProperties length was: %i\n", length);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400330 for (int i = 0; i < length; i++)
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400331 list->push(DEVICE_PROPERTIES[i]);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400332 return list;
333}
that9e0593e2014-10-08 00:01:24 +0200334
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400335MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
336 MtpObjectProperty property,
337 MtpDataPacket& packet) {
that9e0593e2014-10-08 00:01:24 +0200338 MTPD("MyMtpDatabase::getObjectPropertyValue mtpid: %u, property: %x\n", handle, property);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400339 int type;
Ethan Yonker5e083dc2014-09-03 14:46:41 -0500340 MtpResponseCode result = MTP_RESPONSE_INVALID_OBJECT_HANDLE;
that9e0593e2014-10-08 00:01:24 +0200341 MtpStorage::PropEntry prop;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400342 if (!getObjectPropertyInfo(property, type)) {
that9e0593e2014-10-08 00:01:24 +0200343 MTPE("MyMtpDatabase::getObjectPropertyValue returning MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED\n");
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400344 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
345 }
346 std::map<int, MtpStorage*>::iterator storit;
347 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
that9e0593e2014-10-08 00:01:24 +0200348 if (storit->second->getObjectPropertyValue(handle, property, prop) == 0) {
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400349 result = MTP_RESPONSE_OK;
350 break;
351 }
352 }
353
Ethan Yonker5e083dc2014-09-03 14:46:41 -0500354 if (result != MTP_RESPONSE_OK) {
that9e0593e2014-10-08 00:01:24 +0200355 MTPE("MyMtpDatabase::getObjectPropertyValue unable to locate handle: %u\n", handle);
Ethan Yonker5e083dc2014-09-03 14:46:41 -0500356 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
357 }
358
that9e0593e2014-10-08 00:01:24 +0200359 uint64_t longValue = prop.intvalue;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400360 // special case date properties, which are strings to MTP
361 // but stored internally as a uint64
362 if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
363 char date[20];
364 formatDateTime(longValue, date, sizeof(date));
365 packet.putString(date);
366 goto out;
367 }
368 // release date is stored internally as just the year
369 if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
370 char date[20];
371 snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
372 packet.putString(date);
373 goto out;
374 }
375
376 switch (type) {
377 case MTP_TYPE_INT8:
378 packet.putInt8(longValue);
379 break;
380 case MTP_TYPE_UINT8:
381 packet.putUInt8(longValue);
382 break;
383 case MTP_TYPE_INT16:
384 packet.putInt16(longValue);
385 break;
386 case MTP_TYPE_UINT16:
387 packet.putUInt16(longValue);
388 break;
389 case MTP_TYPE_INT32:
390 packet.putInt32(longValue);
391 break;
392 case MTP_TYPE_UINT32:
393 packet.putUInt32(longValue);
394 break;
395 case MTP_TYPE_INT64:
396 packet.putInt64(longValue);
397 break;
398 case MTP_TYPE_UINT64:
399 packet.putUInt64(longValue);
400 break;
401 case MTP_TYPE_INT128:
402 packet.putInt128(longValue);
403 break;
404 case MTP_TYPE_UINT128:
that9e0593e2014-10-08 00:01:24 +0200405 packet.putUInt128(longValue);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400406 break;
407 case MTP_TYPE_STR:
408 {
409 /*std::string stringValue = (string)stringValuesArray[0];
410 if (stringValue) {
411 const char* str = stringValue.c_str();
412 if (str == NULL) {
413 return MTP_RESPONSE_GENERAL_ERROR;
414 }
415 packet.putString(str);
416 } else {
417 packet.putEmptyString();
418 }*/
that9e0593e2014-10-08 00:01:24 +0200419 packet.putString(prop.strvalue.c_str());
420 MTPD("MTP_TYPE_STR: %x = %s\n", prop.property, prop.strvalue.c_str());
421 //MTPE("STRING unsupported type in getObjectPropertyValue\n");
422 //result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400423 break;
424 }
425 default:
426 MTPE("unsupported type in getObjectPropertyValue\n");
427 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
428 }
429out:
430 return result;
431}
432
433MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
434 MtpObjectProperty property,
435 MtpDataPacket& packet) {
436 int type;
437 MTPD("MyMtpDatabase::setObjectPropertyValue start\n");
438 if (!getObjectPropertyInfo(property, type)) {
439 MTPE("MyMtpDatabase::setObjectPropertyValue returning MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED\n");
440 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
441 }
442 MTPD("MyMtpDatabase::setObjectPropertyValue continuing\n");
443 long longValue = 0;
444 std::string stringValue;
445
446 switch (type) {
447 case MTP_TYPE_INT8:
448 MTPD("int8\n");
449 longValue = packet.getInt8();
450 break;
451 case MTP_TYPE_UINT8:
452 MTPD("uint8\n");
453 longValue = packet.getUInt8();
454 break;
455 case MTP_TYPE_INT16:
456 MTPD("int16\n");
457 longValue = packet.getInt16();
458 break;
459 case MTP_TYPE_UINT16:
460 MTPD("uint16\n");
461 longValue = packet.getUInt16();
462 break;
463 case MTP_TYPE_INT32:
464 MTPD("int32\n");
465 longValue = packet.getInt32();
466 break;
467 case MTP_TYPE_UINT32:
468 MTPD("uint32\n");
469 longValue = packet.getUInt32();
470 break;
471 case MTP_TYPE_INT64:
472 MTPD("int64\n");
473 longValue = packet.getInt64();
474 break;
475 case MTP_TYPE_UINT64:
476 MTPD("uint64\n");
477 longValue = packet.getUInt64();
478 break;
479 case MTP_TYPE_STR:
480 {
481 MTPD("string\n");
482 MtpStringBuffer buffer;
483 packet.getString(buffer);
484 stringValue = (const char *)buffer;
485 break;
486 }
487 default:
488 MTPE("MyMtpDatabase::setObjectPropertyValue unsupported type %i in getObjectPropertyValue\n", type);
489 return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
490 }
491
492 int result = MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
493
494 switch (property) {
495 case MTP_PROPERTY_OBJECT_FILE_NAME:
496 {
497 MTPD("MyMtpDatabase::setObjectPropertyValue renaming file, handle: %d, new name: '%s'\n", handle, stringValue.c_str());
498 std::map<int, MtpStorage*>::iterator storit;
499 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
500 if (storit->second->renameObject(handle, stringValue) == 0) {
501 MTPD("MTP_RESPONSE_OK\n");
502 result = MTP_RESPONSE_OK;
503 break;
504 }
505 }
506 }
507 break;
508
509 default:
510 MTPE("MyMtpDatabase::setObjectPropertyValue property %x not supported.\n", property);
511 result = MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
512 }
513 MTPD("MyMtpDatabase::setObjectPropertyValue returning %d\n", result);
514 return result;
515}
516
517MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
518 MtpDataPacket& packet) {
519 int type, result = 0;
520 char prop_value[PROPERTY_VALUE_MAX];
521 MTPD("property %s\n",
522 MtpDebug::getDevicePropCodeName(property));
523 if (!getDevicePropertyInfo(property, type)) {
524 MTPE("MyMtpDatabase::getDevicePropertyValue MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED\n");
525 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
526 }
527 MTPD("property %s\n",
528 MtpDebug::getDevicePropCodeName(property));
529 MTPD("property %x\n", property);
530 MTPD("MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME %x\n", MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME);
531 switch (property) {
532 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
533 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
534 result = MTP_RESPONSE_OK;
535 break;
536 default:
537 {
538 MTPE("MyMtpDatabase::getDevicePropertyValue property %x not supported\n", property);
539 result = MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
540 break;
541 }
542 }
543
544 if (result != MTP_RESPONSE_OK) {
545 MTPD("MTP_REPONSE_OK NOT OK\n");
546 return result;
547 }
548
549 long longValue = 0;
550 property_get("ro.build.product", prop_value, "unknown manufacturer");
551 switch (type) {
552 case MTP_TYPE_INT8: {
553 MTPD("MTP_TYPE_INT8\n");
554 packet.putInt8(longValue);
555 break;
556 }
557 case MTP_TYPE_UINT8:
558 {
559 MTPD("MTP_TYPE_UINT8\n");
560 packet.putUInt8(longValue);
561 break;
562 }
563 case MTP_TYPE_INT16:
564 {
565 MTPD("MTP_TYPE_INT16\n");
566 packet.putInt16(longValue);
567 break;
568 }
569 case MTP_TYPE_UINT16:
570 {
571 MTPD("MTP_TYPE_UINT16\n");
572 packet.putUInt16(longValue);
573 break;
574 }
575 case MTP_TYPE_INT32:
576 {
577 MTPD("MTP_TYPE_INT32\n");
578 packet.putInt32(longValue);
579 break;
580 }
581 case MTP_TYPE_UINT32:
582 {
583 MTPD("MTP_TYPE_UINT32\n");
584 packet.putUInt32(longValue);
585 break;
586 }
587 case MTP_TYPE_INT64:
588 {
589 MTPD("MTP_TYPE_INT64\n");
590 packet.putInt64(longValue);
591 break;
592 }
593 case MTP_TYPE_UINT64:
594 {
595 MTPD("MTP_TYPE_UINT64\n");
596 packet.putUInt64(longValue);
597 break;
598 }
599 case MTP_TYPE_INT128:
600 {
601 MTPD("MTP_TYPE_INT128\n");
602 packet.putInt128(longValue);
603 break;
604 }
605 case MTP_TYPE_UINT128:
606 {
607 MTPD("MTP_TYPE_UINT128\n");
608 packet.putInt128(longValue);
609 break;
610 }
611 case MTP_TYPE_STR:
612 {
613 MTPD("MTP_TYPE_STR\n");
614 char* str = prop_value;
615 packet.putString(str);
616 break;
617 }
618 default:
619 MTPE("MyMtpDatabase::getDevicePropertyValue unsupported type %i in getDevicePropertyValue\n", type);
620 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
621 }
622
623 return MTP_RESPONSE_OK;
624}
625
626MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property, MtpDataPacket& packet) {
627 int type;
628 MTPE("MyMtpDatabase::setDevicePropertyValue not implemented, returning 0\n");
629 return 0;
630}
631
632MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
633 MTPE("MyMtpDatabase::resetDeviceProperty not implemented, returning -1\n");
634 return -1;
635}
636
637MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle, uint32_t format, uint32_t property, int groupCode, int depth, MtpDataPacket& packet) {
638 MTPD("getObjectPropertyList()\n");
639 MTPD("property: %x\n", property);
640 std::map<int, MtpStorage*>::iterator storit;
641 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
642 MTPD("MyMtpDatabase::getObjectPropertyList calling getObjectPropertyList\n");
643 if (storit->second->getObjectPropertyList(handle, format, property, groupCode, depth, packet) == 0) {
644 MTPD("MTP_RESPONSE_OK\n");
645 return MTP_RESPONSE_OK;
646 }
647 }
648 MTPE("MyMtpDatabase::getObjectPropertyList MTP_RESPOSNE_INVALID_OBJECT_HANDLE %i\n", handle);
649 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
650}
651
652MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle, MtpObjectInfo& info) {
653 std::map<int, MtpStorage*>::iterator storit;
654 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
655 if (storit->second->getObjectInfo(handle, info) == 0) {
656 MTPD("MTP_RESPONSE_OK\n");
657 return MTP_RESPONSE_OK;
658 }
659 }
660 MTPE("MyMtpDatabase::getObjectInfo MTP_RESPONSE_INVALID_OBJECT_HANDLE %i\n", handle);
661 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
662}
663
664void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
665 MtpString path;
666 int64_t length;
667 MtpObjectFormat format;
668 void* result = NULL;
669 outThumbSize = 0;
670 MTPE("MyMtpDatabase::getThumbnail not implemented, returning 0\n");
671 return 0;
672}
673
674MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle, MtpString& outFilePath, int64_t& outFileLength, MtpObjectFormat& outFormat) {
675 std::map<int, MtpStorage*>::iterator storit;
676 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400677 MTPD("MyMtpDatabase::getObjectFilePath calling getObjectFilePath\n");
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400678 if (storit->second->getObjectFilePath(handle, outFilePath, outFileLength, outFormat) == 0) {
679 MTPD("MTP_RESPONSE_OK\n");
680 return MTP_RESPONSE_OK;
681 }
682 }
683 MTPE("MyMtpDatabase::getObjectFilePath MTP_RESPOSNE_INVALID_OBJECT_HANDLE %i\n", handle);
684 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
685}
686
687MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
688 MTPD("deleteFile\n");
689 std::map<int, MtpStorage*>::iterator storit;
690 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
691 if (storit->second->deleteFile(handle) == 0) {
692 MTPD("MTP_RESPONSE_OK\n");
693 return MTP_RESPONSE_OK;
694 }
695 }
696 MTPE("MyMtpDatabase::deleteFile MTP_RESPONSE_INVALID_OBJECT_HANDLE %i\n", handle);
697 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
698}
699
700struct PropertyTableEntry {
701 MtpObjectProperty property;
702 int type;
703};
704
705static const PropertyTableEntry kObjectPropertyTable[] = {
706 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
707 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
708 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
709 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
710 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
711 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
712 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
713 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
714 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
715 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
716 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
717 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
718 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
719 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
720 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
721 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
722 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
723 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
724 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
725 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
726};
727
728static const PropertyTableEntry kDevicePropertyTable[] = {
729 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
730 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
731 { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
732};
733
734bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
735 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
736 const PropertyTableEntry* entry = kObjectPropertyTable;
737 MTPD("MyMtpDatabase::getObjectPropertyInfo size is: %i\n", count);
738 for (int i = 0; i < count; i++, entry++) {
739 if (entry->property == property) {
740 type = entry->type;
741 return true;
742 }
743 }
744 return false;
745}
746
747bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
748 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
749 const PropertyTableEntry* entry = kDevicePropertyTable;
750 MTPD("MyMtpDatabase::getDevicePropertyInfo count is: %i\n", count);
751 for (int i = 0; i < count; i++, entry++) {
752 if (entry->property == property) {
753 type = entry->type;
754 MTPD("type: %x\n", type);
755 return true;
756 }
757 }
758 return false;
759}
760
761MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
762 // call function and place files with associated handles into int array
763 MTPD("MyMtpDatabase::getObjectReferences returning null, this seems to be what Android always does.\n");
764 MTPD("handle: %d\n", handle);
765 // Windows + Android seems to always return a NULL in this function, c == null path
766 // The way that this is handled in Android then is to do this:
767 return NULL;
768}
769
770MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
771 MtpObjectHandleList* references) {
772 int count = references->size();
773 MTPE("MyMtpDatabase::setObjectReferences not implemented, returning 0\n");
774 return 0;
775}
776
777MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
778 MtpObjectFormat format) {
779 MTPD("MyMtpDatabase::getObjectPropertyDesc start\n");
780 MtpProperty* result = NULL;
781 switch (property) {
782 case MTP_PROPERTY_OBJECT_FORMAT:
783 // use format as default value
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400784 result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
785 break;
786 case MTP_PROPERTY_PROTECTION_STATUS:
787 case MTP_PROPERTY_TRACK:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400788 result = new MtpProperty(property, MTP_TYPE_UINT16);
789 break;
790 case MTP_PROPERTY_STORAGE_ID:
791 case MTP_PROPERTY_PARENT_OBJECT:
792 case MTP_PROPERTY_DURATION:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400793 result = new MtpProperty(property, MTP_TYPE_UINT32);
794 break;
795 case MTP_PROPERTY_OBJECT_SIZE:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400796 result = new MtpProperty(property, MTP_TYPE_UINT64);
797 break;
798 case MTP_PROPERTY_PERSISTENT_UID:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400799 result = new MtpProperty(property, MTP_TYPE_UINT128);
800 break;
801 case MTP_PROPERTY_NAME:
802 case MTP_PROPERTY_DISPLAY_NAME:
803 case MTP_PROPERTY_ARTIST:
804 case MTP_PROPERTY_ALBUM_NAME:
805 case MTP_PROPERTY_ALBUM_ARTIST:
806 case MTP_PROPERTY_GENRE:
807 case MTP_PROPERTY_COMPOSER:
808 case MTP_PROPERTY_DESCRIPTION:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400809 result = new MtpProperty(property, MTP_TYPE_STR);
810 break;
811 case MTP_PROPERTY_DATE_MODIFIED:
812 case MTP_PROPERTY_DATE_ADDED:
813 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400814 result = new MtpProperty(property, MTP_TYPE_STR);
815 result->setFormDateTime();
816 break;
817 case MTP_PROPERTY_OBJECT_FILE_NAME:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400818 // We allow renaming files and folders
819 result = new MtpProperty(property, MTP_TYPE_STR, true);
820 break;
821 }
822 return result;
823}
824
825MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
826 MtpProperty* result = NULL;
827 int ret;
that9e0593e2014-10-08 00:01:24 +0200828 bool writable = false;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400829 switch (property) {
830 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
831 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
that9e0593e2014-10-08 00:01:24 +0200832 writable = true;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400833 // fall through
834 case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
835 result = new MtpProperty(property, MTP_TYPE_STR, writable);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400836
837 // get current value
that9e0593e2014-10-08 00:01:24 +0200838 // TODO: add actual values
839 result->setCurrentValue('\0');
840 result->setDefaultValue('\0');
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400841 break;
842 }
843
844 return result;
845}
846
847void MyMtpDatabase::sessionStarted() {
848 MTPD("MyMtpDatabase::sessionStarted not implemented or does nothing, returning\n");
849 return;
850}
851
852void MyMtpDatabase::sessionEnded() {
853 MTPD("MyMtpDatabase::sessionEnded not implemented or does nothing, returning\n");
854 return;
855}
856
857// ----------------------------------------------------------------------------
858
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400859void MyMtpDatabase::lockMutex(void) {
860 std::map<int, MtpStorage*>::iterator storit;
861 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
862 storit->second->lockMutex(0);
863 }
864}
865
866void MyMtpDatabase::unlockMutex(void) {
867 std::map<int, MtpStorage*>::iterator storit;
868 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
869 storit->second->unlockMutex(0);
870 }
871}