blob: 05bb5d9fbaed6e104028a6267033baaceb135a47 [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) {
236 storagemap[storageID] = storage;
237 storage->createDB();
238}
239
240MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
241 MtpObjectFormat format,
242 MtpObjectHandle parent) {
243 MTPD("storageID: %d\n", storageID);
that9e0593e2014-10-08 00:01:24 +0200244 MtpObjectHandleList* list = storagemap[storageID]->getObjectList(storageID, parent);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400245 MTPD("list: %d\n", list->size());
246 return list;
247}
248
249int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
250 MtpObjectFormat format,
251 MtpObjectHandle parent) {
that9e0593e2014-10-08 00:01:24 +0200252 MtpObjectHandleList* list = storagemap[storageID]->getObjectList(storageID, parent);
253 int size = list->size();
254 delete list;
255 return size;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400256}
257
258MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
259 // This function tells the host PC which file formats the device supports
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400260 MtpObjectFormatList* list = new MtpObjectFormatList();
that9e0593e2014-10-08 00:01:24 +0200261 int length = sizeof(SUPPORTED_PLAYBACK_FORMATS) / sizeof(SUPPORTED_PLAYBACK_FORMATS[0]);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400262 MTPD("MyMtpDatabase::getSupportedPlaybackFormats length: %i\n", length);
263 for (int i = 0; i < length; i++) {
that9e0593e2014-10-08 00:01:24 +0200264 MTPD("supported playback format: %x\n", SUPPORTED_PLAYBACK_FORMATS[i]);
265 list->push(SUPPORTED_PLAYBACK_FORMATS[i]);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400266 }
267 return list;
268}
269
270MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
271 // Android OS implementation of this function returns NULL
272 // so we are not implementing this function either.
273 MTPD("MyMtpDatabase::getSupportedCaptureFormats returning NULL (This is what Android does as well).\n");
274 return NULL;
275}
276
277MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
278 int* properties;
279 MtpObjectPropertyList* list = new MtpObjectPropertyList();
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400280 int length = 0;
281 switch (format) {
282 case MTP_FORMAT_MP3:
283 case MTP_FORMAT_WAV:
284 case MTP_FORMAT_WMA:
285 case MTP_FORMAT_OGG:
286 case MTP_FORMAT_AAC:
287 properties = AUDIO_PROPERTIES;
288 length = sizeof(AUDIO_PROPERTIES) / sizeof(AUDIO_PROPERTIES[0]);
that9e0593e2014-10-08 00:01:24 +0200289 break;
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400290 case MTP_FORMAT_MPEG:
291 case MTP_FORMAT_3GP_CONTAINER:
292 case MTP_FORMAT_WMV:
293 properties = VIDEO_PROPERTIES;
294 length = sizeof(VIDEO_PROPERTIES) / sizeof(VIDEO_PROPERTIES[0]);
that9e0593e2014-10-08 00:01:24 +0200295 break;
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400296 case MTP_FORMAT_EXIF_JPEG:
297 case MTP_FORMAT_GIF:
298 case MTP_FORMAT_PNG:
299 case MTP_FORMAT_BMP:
300 properties = IMAGE_PROPERTIES;
301 length = sizeof(IMAGE_PROPERTIES) / sizeof(IMAGE_PROPERTIES[0]);
that9e0593e2014-10-08 00:01:24 +0200302 break;
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400303 case 0:
304 properties = ALL_PROPERTIES;
305 length = sizeof(ALL_PROPERTIES) / sizeof(ALL_PROPERTIES[0]);
that9e0593e2014-10-08 00:01:24 +0200306 break;
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400307 default:
308 properties = FILE_PROPERTIES;
309 length = sizeof(FILE_PROPERTIES) / sizeof(FILE_PROPERTIES[0]);
310 }
that9e0593e2014-10-08 00:01:24 +0200311 MTPD("MyMtpDatabase::getSupportedObjectProperties length is: %i, format: %x", length, format);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400312 for (int i = 0; i < length; i++) {
313 MTPD("supported object property: %x\n", properties[i]);
314 list->push(properties[i]);
315 }
316 return list;
317}
318
319MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400320 MtpDevicePropertyList* list = new MtpDevicePropertyList();
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400321 int length = sizeof(DEVICE_PROPERTIES) / sizeof(DEVICE_PROPERTIES[0]);
that9e0593e2014-10-08 00:01:24 +0200322 MTPD("MyMtpDatabase::getSupportedDeviceProperties length was: %i\n", length);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400323 for (int i = 0; i < length; i++)
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400324 list->push(DEVICE_PROPERTIES[i]);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400325 return list;
326}
that9e0593e2014-10-08 00:01:24 +0200327
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400328MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
329 MtpObjectProperty property,
330 MtpDataPacket& packet) {
that9e0593e2014-10-08 00:01:24 +0200331 MTPD("MyMtpDatabase::getObjectPropertyValue mtpid: %u, property: %x\n", handle, property);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400332 int type;
Ethan Yonker5e083dc2014-09-03 14:46:41 -0500333 MtpResponseCode result = MTP_RESPONSE_INVALID_OBJECT_HANDLE;
that9e0593e2014-10-08 00:01:24 +0200334 MtpStorage::PropEntry prop;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400335 if (!getObjectPropertyInfo(property, type)) {
that9e0593e2014-10-08 00:01:24 +0200336 MTPE("MyMtpDatabase::getObjectPropertyValue returning MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED\n");
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400337 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
338 }
339 std::map<int, MtpStorage*>::iterator storit;
340 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
that9e0593e2014-10-08 00:01:24 +0200341 if (storit->second->getObjectPropertyValue(handle, property, prop) == 0) {
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400342 result = MTP_RESPONSE_OK;
343 break;
344 }
345 }
346
Ethan Yonker5e083dc2014-09-03 14:46:41 -0500347 if (result != MTP_RESPONSE_OK) {
that9e0593e2014-10-08 00:01:24 +0200348 MTPE("MyMtpDatabase::getObjectPropertyValue unable to locate handle: %u\n", handle);
Ethan Yonker5e083dc2014-09-03 14:46:41 -0500349 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
350 }
351
that9e0593e2014-10-08 00:01:24 +0200352 uint64_t longValue = prop.intvalue;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400353 // special case date properties, which are strings to MTP
354 // but stored internally as a uint64
355 if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
356 char date[20];
357 formatDateTime(longValue, date, sizeof(date));
358 packet.putString(date);
359 goto out;
360 }
361 // release date is stored internally as just the year
362 if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
363 char date[20];
364 snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
365 packet.putString(date);
366 goto out;
367 }
368
369 switch (type) {
370 case MTP_TYPE_INT8:
371 packet.putInt8(longValue);
372 break;
373 case MTP_TYPE_UINT8:
374 packet.putUInt8(longValue);
375 break;
376 case MTP_TYPE_INT16:
377 packet.putInt16(longValue);
378 break;
379 case MTP_TYPE_UINT16:
380 packet.putUInt16(longValue);
381 break;
382 case MTP_TYPE_INT32:
383 packet.putInt32(longValue);
384 break;
385 case MTP_TYPE_UINT32:
386 packet.putUInt32(longValue);
387 break;
388 case MTP_TYPE_INT64:
389 packet.putInt64(longValue);
390 break;
391 case MTP_TYPE_UINT64:
392 packet.putUInt64(longValue);
393 break;
394 case MTP_TYPE_INT128:
395 packet.putInt128(longValue);
396 break;
397 case MTP_TYPE_UINT128:
that9e0593e2014-10-08 00:01:24 +0200398 packet.putUInt128(longValue);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400399 break;
400 case MTP_TYPE_STR:
401 {
402 /*std::string stringValue = (string)stringValuesArray[0];
403 if (stringValue) {
404 const char* str = stringValue.c_str();
405 if (str == NULL) {
406 return MTP_RESPONSE_GENERAL_ERROR;
407 }
408 packet.putString(str);
409 } else {
410 packet.putEmptyString();
411 }*/
that9e0593e2014-10-08 00:01:24 +0200412 packet.putString(prop.strvalue.c_str());
413 MTPD("MTP_TYPE_STR: %x = %s\n", prop.property, prop.strvalue.c_str());
414 //MTPE("STRING unsupported type in getObjectPropertyValue\n");
415 //result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400416 break;
417 }
418 default:
419 MTPE("unsupported type in getObjectPropertyValue\n");
420 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
421 }
422out:
423 return result;
424}
425
426MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
427 MtpObjectProperty property,
428 MtpDataPacket& packet) {
429 int type;
430 MTPD("MyMtpDatabase::setObjectPropertyValue start\n");
431 if (!getObjectPropertyInfo(property, type)) {
432 MTPE("MyMtpDatabase::setObjectPropertyValue returning MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED\n");
433 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
434 }
435 MTPD("MyMtpDatabase::setObjectPropertyValue continuing\n");
436 long longValue = 0;
437 std::string stringValue;
438
439 switch (type) {
440 case MTP_TYPE_INT8:
441 MTPD("int8\n");
442 longValue = packet.getInt8();
443 break;
444 case MTP_TYPE_UINT8:
445 MTPD("uint8\n");
446 longValue = packet.getUInt8();
447 break;
448 case MTP_TYPE_INT16:
449 MTPD("int16\n");
450 longValue = packet.getInt16();
451 break;
452 case MTP_TYPE_UINT16:
453 MTPD("uint16\n");
454 longValue = packet.getUInt16();
455 break;
456 case MTP_TYPE_INT32:
457 MTPD("int32\n");
458 longValue = packet.getInt32();
459 break;
460 case MTP_TYPE_UINT32:
461 MTPD("uint32\n");
462 longValue = packet.getUInt32();
463 break;
464 case MTP_TYPE_INT64:
465 MTPD("int64\n");
466 longValue = packet.getInt64();
467 break;
468 case MTP_TYPE_UINT64:
469 MTPD("uint64\n");
470 longValue = packet.getUInt64();
471 break;
472 case MTP_TYPE_STR:
473 {
474 MTPD("string\n");
475 MtpStringBuffer buffer;
476 packet.getString(buffer);
477 stringValue = (const char *)buffer;
478 break;
479 }
480 default:
481 MTPE("MyMtpDatabase::setObjectPropertyValue unsupported type %i in getObjectPropertyValue\n", type);
482 return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
483 }
484
485 int result = MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
486
487 switch (property) {
488 case MTP_PROPERTY_OBJECT_FILE_NAME:
489 {
490 MTPD("MyMtpDatabase::setObjectPropertyValue renaming file, handle: %d, new name: '%s'\n", handle, stringValue.c_str());
491 std::map<int, MtpStorage*>::iterator storit;
492 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
493 if (storit->second->renameObject(handle, stringValue) == 0) {
494 MTPD("MTP_RESPONSE_OK\n");
495 result = MTP_RESPONSE_OK;
496 break;
497 }
498 }
499 }
500 break;
501
502 default:
503 MTPE("MyMtpDatabase::setObjectPropertyValue property %x not supported.\n", property);
504 result = MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
505 }
506 MTPD("MyMtpDatabase::setObjectPropertyValue returning %d\n", result);
507 return result;
508}
509
510MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
511 MtpDataPacket& packet) {
512 int type, result = 0;
513 char prop_value[PROPERTY_VALUE_MAX];
514 MTPD("property %s\n",
515 MtpDebug::getDevicePropCodeName(property));
516 if (!getDevicePropertyInfo(property, type)) {
517 MTPE("MyMtpDatabase::getDevicePropertyValue MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED\n");
518 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
519 }
520 MTPD("property %s\n",
521 MtpDebug::getDevicePropCodeName(property));
522 MTPD("property %x\n", property);
523 MTPD("MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME %x\n", MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME);
524 switch (property) {
525 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
526 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
527 result = MTP_RESPONSE_OK;
528 break;
529 default:
530 {
531 MTPE("MyMtpDatabase::getDevicePropertyValue property %x not supported\n", property);
532 result = MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
533 break;
534 }
535 }
536
537 if (result != MTP_RESPONSE_OK) {
538 MTPD("MTP_REPONSE_OK NOT OK\n");
539 return result;
540 }
541
542 long longValue = 0;
543 property_get("ro.build.product", prop_value, "unknown manufacturer");
544 switch (type) {
545 case MTP_TYPE_INT8: {
546 MTPD("MTP_TYPE_INT8\n");
547 packet.putInt8(longValue);
548 break;
549 }
550 case MTP_TYPE_UINT8:
551 {
552 MTPD("MTP_TYPE_UINT8\n");
553 packet.putUInt8(longValue);
554 break;
555 }
556 case MTP_TYPE_INT16:
557 {
558 MTPD("MTP_TYPE_INT16\n");
559 packet.putInt16(longValue);
560 break;
561 }
562 case MTP_TYPE_UINT16:
563 {
564 MTPD("MTP_TYPE_UINT16\n");
565 packet.putUInt16(longValue);
566 break;
567 }
568 case MTP_TYPE_INT32:
569 {
570 MTPD("MTP_TYPE_INT32\n");
571 packet.putInt32(longValue);
572 break;
573 }
574 case MTP_TYPE_UINT32:
575 {
576 MTPD("MTP_TYPE_UINT32\n");
577 packet.putUInt32(longValue);
578 break;
579 }
580 case MTP_TYPE_INT64:
581 {
582 MTPD("MTP_TYPE_INT64\n");
583 packet.putInt64(longValue);
584 break;
585 }
586 case MTP_TYPE_UINT64:
587 {
588 MTPD("MTP_TYPE_UINT64\n");
589 packet.putUInt64(longValue);
590 break;
591 }
592 case MTP_TYPE_INT128:
593 {
594 MTPD("MTP_TYPE_INT128\n");
595 packet.putInt128(longValue);
596 break;
597 }
598 case MTP_TYPE_UINT128:
599 {
600 MTPD("MTP_TYPE_UINT128\n");
601 packet.putInt128(longValue);
602 break;
603 }
604 case MTP_TYPE_STR:
605 {
606 MTPD("MTP_TYPE_STR\n");
607 char* str = prop_value;
608 packet.putString(str);
609 break;
610 }
611 default:
612 MTPE("MyMtpDatabase::getDevicePropertyValue unsupported type %i in getDevicePropertyValue\n", type);
613 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
614 }
615
616 return MTP_RESPONSE_OK;
617}
618
619MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property, MtpDataPacket& packet) {
620 int type;
621 MTPE("MyMtpDatabase::setDevicePropertyValue not implemented, returning 0\n");
622 return 0;
623}
624
625MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
626 MTPE("MyMtpDatabase::resetDeviceProperty not implemented, returning -1\n");
627 return -1;
628}
629
630MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle, uint32_t format, uint32_t property, int groupCode, int depth, MtpDataPacket& packet) {
631 MTPD("getObjectPropertyList()\n");
632 MTPD("property: %x\n", property);
633 std::map<int, MtpStorage*>::iterator storit;
634 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
635 MTPD("MyMtpDatabase::getObjectPropertyList calling getObjectPropertyList\n");
636 if (storit->second->getObjectPropertyList(handle, format, property, groupCode, depth, packet) == 0) {
637 MTPD("MTP_RESPONSE_OK\n");
638 return MTP_RESPONSE_OK;
639 }
640 }
641 MTPE("MyMtpDatabase::getObjectPropertyList MTP_RESPOSNE_INVALID_OBJECT_HANDLE %i\n", handle);
642 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
643}
644
645MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle, MtpObjectInfo& info) {
646 std::map<int, MtpStorage*>::iterator storit;
647 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
648 if (storit->second->getObjectInfo(handle, info) == 0) {
649 MTPD("MTP_RESPONSE_OK\n");
650 return MTP_RESPONSE_OK;
651 }
652 }
653 MTPE("MyMtpDatabase::getObjectInfo MTP_RESPONSE_INVALID_OBJECT_HANDLE %i\n", handle);
654 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
655}
656
657void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
658 MtpString path;
659 int64_t length;
660 MtpObjectFormat format;
661 void* result = NULL;
662 outThumbSize = 0;
663 MTPE("MyMtpDatabase::getThumbnail not implemented, returning 0\n");
664 return 0;
665}
666
667MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle, MtpString& outFilePath, int64_t& outFileLength, MtpObjectFormat& outFormat) {
668 std::map<int, MtpStorage*>::iterator storit;
669 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400670 MTPD("MyMtpDatabase::getObjectFilePath calling getObjectFilePath\n");
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400671 if (storit->second->getObjectFilePath(handle, outFilePath, outFileLength, outFormat) == 0) {
672 MTPD("MTP_RESPONSE_OK\n");
673 return MTP_RESPONSE_OK;
674 }
675 }
676 MTPE("MyMtpDatabase::getObjectFilePath MTP_RESPOSNE_INVALID_OBJECT_HANDLE %i\n", handle);
677 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
678}
679
680MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
681 MTPD("deleteFile\n");
682 std::map<int, MtpStorage*>::iterator storit;
683 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
684 if (storit->second->deleteFile(handle) == 0) {
685 MTPD("MTP_RESPONSE_OK\n");
686 return MTP_RESPONSE_OK;
687 }
688 }
689 MTPE("MyMtpDatabase::deleteFile MTP_RESPONSE_INVALID_OBJECT_HANDLE %i\n", handle);
690 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
691}
692
693struct PropertyTableEntry {
694 MtpObjectProperty property;
695 int type;
696};
697
698static const PropertyTableEntry kObjectPropertyTable[] = {
699 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
700 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
701 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
702 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
703 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
704 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
705 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
706 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
707 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
708 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
709 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
710 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
711 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
712 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
713 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
714 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
715 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
716 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
717 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
718 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
719};
720
721static const PropertyTableEntry kDevicePropertyTable[] = {
722 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
723 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
724 { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
725};
726
727bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
728 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
729 const PropertyTableEntry* entry = kObjectPropertyTable;
730 MTPD("MyMtpDatabase::getObjectPropertyInfo size is: %i\n", count);
731 for (int i = 0; i < count; i++, entry++) {
732 if (entry->property == property) {
733 type = entry->type;
734 return true;
735 }
736 }
737 return false;
738}
739
740bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
741 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
742 const PropertyTableEntry* entry = kDevicePropertyTable;
743 MTPD("MyMtpDatabase::getDevicePropertyInfo count is: %i\n", count);
744 for (int i = 0; i < count; i++, entry++) {
745 if (entry->property == property) {
746 type = entry->type;
747 MTPD("type: %x\n", type);
748 return true;
749 }
750 }
751 return false;
752}
753
754MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
755 // call function and place files with associated handles into int array
756 MTPD("MyMtpDatabase::getObjectReferences returning null, this seems to be what Android always does.\n");
757 MTPD("handle: %d\n", handle);
758 // Windows + Android seems to always return a NULL in this function, c == null path
759 // The way that this is handled in Android then is to do this:
760 return NULL;
761}
762
763MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
764 MtpObjectHandleList* references) {
765 int count = references->size();
766 MTPE("MyMtpDatabase::setObjectReferences not implemented, returning 0\n");
767 return 0;
768}
769
770MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
771 MtpObjectFormat format) {
772 MTPD("MyMtpDatabase::getObjectPropertyDesc start\n");
773 MtpProperty* result = NULL;
774 switch (property) {
775 case MTP_PROPERTY_OBJECT_FORMAT:
776 // use format as default value
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400777 result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
778 break;
779 case MTP_PROPERTY_PROTECTION_STATUS:
780 case MTP_PROPERTY_TRACK:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400781 result = new MtpProperty(property, MTP_TYPE_UINT16);
782 break;
783 case MTP_PROPERTY_STORAGE_ID:
784 case MTP_PROPERTY_PARENT_OBJECT:
785 case MTP_PROPERTY_DURATION:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400786 result = new MtpProperty(property, MTP_TYPE_UINT32);
787 break;
788 case MTP_PROPERTY_OBJECT_SIZE:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400789 result = new MtpProperty(property, MTP_TYPE_UINT64);
790 break;
791 case MTP_PROPERTY_PERSISTENT_UID:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400792 result = new MtpProperty(property, MTP_TYPE_UINT128);
793 break;
794 case MTP_PROPERTY_NAME:
795 case MTP_PROPERTY_DISPLAY_NAME:
796 case MTP_PROPERTY_ARTIST:
797 case MTP_PROPERTY_ALBUM_NAME:
798 case MTP_PROPERTY_ALBUM_ARTIST:
799 case MTP_PROPERTY_GENRE:
800 case MTP_PROPERTY_COMPOSER:
801 case MTP_PROPERTY_DESCRIPTION:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400802 result = new MtpProperty(property, MTP_TYPE_STR);
803 break;
804 case MTP_PROPERTY_DATE_MODIFIED:
805 case MTP_PROPERTY_DATE_ADDED:
806 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400807 result = new MtpProperty(property, MTP_TYPE_STR);
808 result->setFormDateTime();
809 break;
810 case MTP_PROPERTY_OBJECT_FILE_NAME:
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400811 // We allow renaming files and folders
812 result = new MtpProperty(property, MTP_TYPE_STR, true);
813 break;
814 }
815 return result;
816}
817
818MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
819 MtpProperty* result = NULL;
820 int ret;
that9e0593e2014-10-08 00:01:24 +0200821 bool writable = false;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400822 switch (property) {
823 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
824 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
that9e0593e2014-10-08 00:01:24 +0200825 writable = true;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400826 // fall through
827 case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
828 result = new MtpProperty(property, MTP_TYPE_STR, writable);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400829
830 // get current value
that9e0593e2014-10-08 00:01:24 +0200831 // TODO: add actual values
832 result->setCurrentValue('\0');
833 result->setDefaultValue('\0');
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400834 break;
835 }
836
837 return result;
838}
839
840void MyMtpDatabase::sessionStarted() {
841 MTPD("MyMtpDatabase::sessionStarted not implemented or does nothing, returning\n");
842 return;
843}
844
845void MyMtpDatabase::sessionEnded() {
846 MTPD("MyMtpDatabase::sessionEnded not implemented or does nothing, returning\n");
847 return;
848}
849
850// ----------------------------------------------------------------------------
851
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400852void MyMtpDatabase::lockMutex(void) {
853 std::map<int, MtpStorage*>::iterator storit;
854 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
855 storit->second->lockMutex(0);
856 }
857}
858
859void MyMtpDatabase::unlockMutex(void) {
860 std::map<int, MtpStorage*>::iterator storit;
861 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
862 storit->second->unlockMutex(0);
863 }
864}