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