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