blob: acdab523d4107632c701b18d134676e176ebf5f1 [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;
Ethan Yonker5e083dc2014-09-03 14:46:41 -0500325 MtpResponseCode result = MTP_RESPONSE_INVALID_OBJECT_HANDLE;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400326 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
Ethan Yonker5e083dc2014-09-03 14:46:41 -0500339 if (result != MTP_RESPONSE_OK) {
340 MTPE("MyMtpDatabase::setObjectPropertyValue unable to locate handle: %i\n", handle);
341 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
342 }
343
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400344 // special case date properties, which are strings to MTP
345 // but stored internally as a uint64
346 if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
347 char date[20];
348 formatDateTime(longValue, date, sizeof(date));
349 packet.putString(date);
350 goto out;
351 }
352 // release date is stored internally as just the year
353 if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
354 char date[20];
355 snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
356 packet.putString(date);
357 goto out;
358 }
359
360 switch (type) {
361 case MTP_TYPE_INT8:
362 packet.putInt8(longValue);
363 break;
364 case MTP_TYPE_UINT8:
365 packet.putUInt8(longValue);
366 break;
367 case MTP_TYPE_INT16:
368 packet.putInt16(longValue);
369 break;
370 case MTP_TYPE_UINT16:
371 packet.putUInt16(longValue);
372 break;
373 case MTP_TYPE_INT32:
374 packet.putInt32(longValue);
375 break;
376 case MTP_TYPE_UINT32:
377 packet.putUInt32(longValue);
378 break;
379 case MTP_TYPE_INT64:
380 packet.putInt64(longValue);
381 break;
382 case MTP_TYPE_UINT64:
383 packet.putUInt64(longValue);
384 break;
385 case MTP_TYPE_INT128:
386 packet.putInt128(longValue);
387 break;
388 case MTP_TYPE_UINT128:
389 packet.putInt128(longValue);
390 break;
391 case MTP_TYPE_STR:
392 {
393 /*std::string stringValue = (string)stringValuesArray[0];
394 if (stringValue) {
395 const char* str = stringValue.c_str();
396 if (str == NULL) {
397 return MTP_RESPONSE_GENERAL_ERROR;
398 }
399 packet.putString(str);
400 } else {
401 packet.putEmptyString();
402 }*/
403 MTPE("STRING unsupported type in getObjectPropertyValue\n");
404 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
405 break;
406 }
407 default:
408 MTPE("unsupported type in getObjectPropertyValue\n");
409 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
410 }
411out:
412 return result;
413}
414
415MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
416 MtpObjectProperty property,
417 MtpDataPacket& packet) {
418 int type;
419 MTPD("MyMtpDatabase::setObjectPropertyValue start\n");
420 if (!getObjectPropertyInfo(property, type)) {
421 MTPE("MyMtpDatabase::setObjectPropertyValue returning MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED\n");
422 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
423 }
424 MTPD("MyMtpDatabase::setObjectPropertyValue continuing\n");
425 long longValue = 0;
426 std::string stringValue;
427
428 switch (type) {
429 case MTP_TYPE_INT8:
430 MTPD("int8\n");
431 longValue = packet.getInt8();
432 break;
433 case MTP_TYPE_UINT8:
434 MTPD("uint8\n");
435 longValue = packet.getUInt8();
436 break;
437 case MTP_TYPE_INT16:
438 MTPD("int16\n");
439 longValue = packet.getInt16();
440 break;
441 case MTP_TYPE_UINT16:
442 MTPD("uint16\n");
443 longValue = packet.getUInt16();
444 break;
445 case MTP_TYPE_INT32:
446 MTPD("int32\n");
447 longValue = packet.getInt32();
448 break;
449 case MTP_TYPE_UINT32:
450 MTPD("uint32\n");
451 longValue = packet.getUInt32();
452 break;
453 case MTP_TYPE_INT64:
454 MTPD("int64\n");
455 longValue = packet.getInt64();
456 break;
457 case MTP_TYPE_UINT64:
458 MTPD("uint64\n");
459 longValue = packet.getUInt64();
460 break;
461 case MTP_TYPE_STR:
462 {
463 MTPD("string\n");
464 MtpStringBuffer buffer;
465 packet.getString(buffer);
466 stringValue = (const char *)buffer;
467 break;
468 }
469 default:
470 MTPE("MyMtpDatabase::setObjectPropertyValue unsupported type %i in getObjectPropertyValue\n", type);
471 return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
472 }
473
474 int result = MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
475
476 switch (property) {
477 case MTP_PROPERTY_OBJECT_FILE_NAME:
478 {
479 MTPD("MyMtpDatabase::setObjectPropertyValue renaming file, handle: %d, new name: '%s'\n", handle, stringValue.c_str());
480 std::map<int, MtpStorage*>::iterator storit;
481 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
482 if (storit->second->renameObject(handle, stringValue) == 0) {
483 MTPD("MTP_RESPONSE_OK\n");
484 result = MTP_RESPONSE_OK;
485 break;
486 }
487 }
488 }
489 break;
490
491 default:
492 MTPE("MyMtpDatabase::setObjectPropertyValue property %x not supported.\n", property);
493 result = MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
494 }
495 MTPD("MyMtpDatabase::setObjectPropertyValue returning %d\n", result);
496 return result;
497}
498
499MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
500 MtpDataPacket& packet) {
501 int type, result = 0;
502 char prop_value[PROPERTY_VALUE_MAX];
503 MTPD("property %s\n",
504 MtpDebug::getDevicePropCodeName(property));
505 if (!getDevicePropertyInfo(property, type)) {
506 MTPE("MyMtpDatabase::getDevicePropertyValue MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED\n");
507 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
508 }
509 MTPD("property %s\n",
510 MtpDebug::getDevicePropCodeName(property));
511 MTPD("property %x\n", property);
512 MTPD("MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME %x\n", MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME);
513 switch (property) {
514 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
515 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
516 result = MTP_RESPONSE_OK;
517 break;
518 default:
519 {
520 MTPE("MyMtpDatabase::getDevicePropertyValue property %x not supported\n", property);
521 result = MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
522 break;
523 }
524 }
525
526 if (result != MTP_RESPONSE_OK) {
527 MTPD("MTP_REPONSE_OK NOT OK\n");
528 return result;
529 }
530
531 long longValue = 0;
532 property_get("ro.build.product", prop_value, "unknown manufacturer");
533 switch (type) {
534 case MTP_TYPE_INT8: {
535 MTPD("MTP_TYPE_INT8\n");
536 packet.putInt8(longValue);
537 break;
538 }
539 case MTP_TYPE_UINT8:
540 {
541 MTPD("MTP_TYPE_UINT8\n");
542 packet.putUInt8(longValue);
543 break;
544 }
545 case MTP_TYPE_INT16:
546 {
547 MTPD("MTP_TYPE_INT16\n");
548 packet.putInt16(longValue);
549 break;
550 }
551 case MTP_TYPE_UINT16:
552 {
553 MTPD("MTP_TYPE_UINT16\n");
554 packet.putUInt16(longValue);
555 break;
556 }
557 case MTP_TYPE_INT32:
558 {
559 MTPD("MTP_TYPE_INT32\n");
560 packet.putInt32(longValue);
561 break;
562 }
563 case MTP_TYPE_UINT32:
564 {
565 MTPD("MTP_TYPE_UINT32\n");
566 packet.putUInt32(longValue);
567 break;
568 }
569 case MTP_TYPE_INT64:
570 {
571 MTPD("MTP_TYPE_INT64\n");
572 packet.putInt64(longValue);
573 break;
574 }
575 case MTP_TYPE_UINT64:
576 {
577 MTPD("MTP_TYPE_UINT64\n");
578 packet.putUInt64(longValue);
579 break;
580 }
581 case MTP_TYPE_INT128:
582 {
583 MTPD("MTP_TYPE_INT128\n");
584 packet.putInt128(longValue);
585 break;
586 }
587 case MTP_TYPE_UINT128:
588 {
589 MTPD("MTP_TYPE_UINT128\n");
590 packet.putInt128(longValue);
591 break;
592 }
593 case MTP_TYPE_STR:
594 {
595 MTPD("MTP_TYPE_STR\n");
596 char* str = prop_value;
597 packet.putString(str);
598 break;
599 }
600 default:
601 MTPE("MyMtpDatabase::getDevicePropertyValue unsupported type %i in getDevicePropertyValue\n", type);
602 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
603 }
604
605 return MTP_RESPONSE_OK;
606}
607
608MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property, MtpDataPacket& packet) {
609 int type;
610 MTPE("MyMtpDatabase::setDevicePropertyValue not implemented, returning 0\n");
611 return 0;
612}
613
614MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
615 MTPE("MyMtpDatabase::resetDeviceProperty not implemented, returning -1\n");
616 return -1;
617}
618
619MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle, uint32_t format, uint32_t property, int groupCode, int depth, MtpDataPacket& packet) {
620 MTPD("getObjectPropertyList()\n");
621 MTPD("property: %x\n", property);
622 std::map<int, MtpStorage*>::iterator storit;
623 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
624 MTPD("MyMtpDatabase::getObjectPropertyList calling getObjectPropertyList\n");
625 if (storit->second->getObjectPropertyList(handle, format, property, groupCode, depth, packet) == 0) {
626 MTPD("MTP_RESPONSE_OK\n");
627 return MTP_RESPONSE_OK;
628 }
629 }
630 MTPE("MyMtpDatabase::getObjectPropertyList MTP_RESPOSNE_INVALID_OBJECT_HANDLE %i\n", handle);
631 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
632}
633
634MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle, MtpObjectInfo& info) {
635 std::map<int, MtpStorage*>::iterator storit;
636 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
637 if (storit->second->getObjectInfo(handle, info) == 0) {
638 MTPD("MTP_RESPONSE_OK\n");
639 return MTP_RESPONSE_OK;
640 }
641 }
642 MTPE("MyMtpDatabase::getObjectInfo MTP_RESPONSE_INVALID_OBJECT_HANDLE %i\n", handle);
643 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
644}
645
646void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
647 MtpString path;
648 int64_t length;
649 MtpObjectFormat format;
650 void* result = NULL;
651 outThumbSize = 0;
652 MTPE("MyMtpDatabase::getThumbnail not implemented, returning 0\n");
653 return 0;
654}
655
656MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle, MtpString& outFilePath, int64_t& outFileLength, MtpObjectFormat& outFormat) {
657 std::map<int, MtpStorage*>::iterator storit;
658 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
659 MTPD("MyMtpDatabase::getObjectFilePath calling getObhectFilePath\n");
660 if (storit->second->getObjectFilePath(handle, outFilePath, outFileLength, outFormat) == 0) {
661 MTPD("MTP_RESPONSE_OK\n");
662 return MTP_RESPONSE_OK;
663 }
664 }
665 MTPE("MyMtpDatabase::getObjectFilePath MTP_RESPOSNE_INVALID_OBJECT_HANDLE %i\n", handle);
666 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
667}
668
669MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
670 MTPD("deleteFile\n");
671 std::map<int, MtpStorage*>::iterator storit;
672 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
673 if (storit->second->deleteFile(handle) == 0) {
674 MTPD("MTP_RESPONSE_OK\n");
675 return MTP_RESPONSE_OK;
676 }
677 }
678 MTPE("MyMtpDatabase::deleteFile MTP_RESPONSE_INVALID_OBJECT_HANDLE %i\n", handle);
679 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
680}
681
682struct PropertyTableEntry {
683 MtpObjectProperty property;
684 int type;
685};
686
687static const PropertyTableEntry kObjectPropertyTable[] = {
688 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
689 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
690 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
691 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
692 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
693 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
694 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
695 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
696 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
697 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
698 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
699 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
700 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
701 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
702 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
703 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
704 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
705 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
706 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
707 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
708};
709
710static const PropertyTableEntry kDevicePropertyTable[] = {
711 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
712 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
713 { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
714};
715
716bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
717 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
718 const PropertyTableEntry* entry = kObjectPropertyTable;
719 MTPD("MyMtpDatabase::getObjectPropertyInfo size is: %i\n", count);
720 for (int i = 0; i < count; i++, entry++) {
721 if (entry->property == property) {
722 type = entry->type;
723 return true;
724 }
725 }
726 return false;
727}
728
729bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
730 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
731 const PropertyTableEntry* entry = kDevicePropertyTable;
732 MTPD("MyMtpDatabase::getDevicePropertyInfo count is: %i\n", count);
733 for (int i = 0; i < count; i++, entry++) {
734 if (entry->property == property) {
735 type = entry->type;
736 MTPD("type: %x\n", type);
737 return true;
738 }
739 }
740 return false;
741}
742
743MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
744 // call function and place files with associated handles into int array
745 MTPD("MyMtpDatabase::getObjectReferences returning null, this seems to be what Android always does.\n");
746 MTPD("handle: %d\n", handle);
747 // Windows + Android seems to always return a NULL in this function, c == null path
748 // The way that this is handled in Android then is to do this:
749 return NULL;
750}
751
752MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
753 MtpObjectHandleList* references) {
754 int count = references->size();
755 MTPE("MyMtpDatabase::setObjectReferences not implemented, returning 0\n");
756 return 0;
757}
758
759MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
760 MtpObjectFormat format) {
761 MTPD("MyMtpDatabase::getObjectPropertyDesc start\n");
762 MtpProperty* result = NULL;
763 switch (property) {
764 case MTP_PROPERTY_OBJECT_FORMAT:
765 // use format as default value
766 MTPD("MyMtpDatabase::getObjectPropertyDesc format\n");
767 result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
768 break;
769 case MTP_PROPERTY_PROTECTION_STATUS:
770 case MTP_PROPERTY_TRACK:
771 MTPD("MyMtpDatabase::getObjectPropertyDesc track\n");
772 result = new MtpProperty(property, MTP_TYPE_UINT16);
773 break;
774 case MTP_PROPERTY_STORAGE_ID:
775 case MTP_PROPERTY_PARENT_OBJECT:
776 case MTP_PROPERTY_DURATION:
777 MTPD("MyMtpDatabase::getObjectPropertyDesc duration\n");
778 result = new MtpProperty(property, MTP_TYPE_UINT32);
779 break;
780 case MTP_PROPERTY_OBJECT_SIZE:
781 MTPD("MyMtpDatabase::getObjectPropertyDesc size\n");
782 result = new MtpProperty(property, MTP_TYPE_UINT64);
783 break;
784 case MTP_PROPERTY_PERSISTENT_UID:
785 MTPD("MyMtpDatabase::getObjectPropertyDesc persistent uid\n");
786 result = new MtpProperty(property, MTP_TYPE_UINT128);
787 break;
788 case MTP_PROPERTY_NAME:
789 case MTP_PROPERTY_DISPLAY_NAME:
790 case MTP_PROPERTY_ARTIST:
791 case MTP_PROPERTY_ALBUM_NAME:
792 case MTP_PROPERTY_ALBUM_ARTIST:
793 case MTP_PROPERTY_GENRE:
794 case MTP_PROPERTY_COMPOSER:
795 case MTP_PROPERTY_DESCRIPTION:
796 MTPD("MyMtpDatabase::getObjectPropertyDesc description\n");
797 result = new MtpProperty(property, MTP_TYPE_STR);
798 break;
799 case MTP_PROPERTY_DATE_MODIFIED:
800 case MTP_PROPERTY_DATE_ADDED:
801 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
802 MTPD("MyMtpDatabase::getObjectPropertyDesc date\n");
803 result = new MtpProperty(property, MTP_TYPE_STR);
804 result->setFormDateTime();
805 break;
806 case MTP_PROPERTY_OBJECT_FILE_NAME:
807 MTPD("MyMtpDatabase::getObjectPropertyDesc file name\n");
808 // We allow renaming files and folders
809 result = new MtpProperty(property, MTP_TYPE_STR, true);
810 break;
811 }
812 return result;
813}
814
815MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
816 MtpProperty* result = NULL;
817 int ret;
818 bool writable = true;
819 switch (property) {
820 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
821 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
822 ret = MTP_RESPONSE_OK;
823 // fall through
824 case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
825 result = new MtpProperty(property, MTP_TYPE_STR, writable);
826 ret = MTP_RESPONSE_OK;
827
828 // get current value
829 if (ret == MTP_RESPONSE_OK) {
830 MTPD("here\n");
831 result->setCurrentValue('\0');
832 result->setDefaultValue('\0');
833 } else {
834 MTPE("unable to read device property, response: %04X", ret);
835 }
836 break;
837 default:
838 ret = MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
839 break;
840 }
841
842 return result;
843}
844
845void MyMtpDatabase::sessionStarted() {
846 MTPD("MyMtpDatabase::sessionStarted not implemented or does nothing, returning\n");
847 return;
848}
849
850void MyMtpDatabase::sessionEnded() {
851 MTPD("MyMtpDatabase::sessionEnded not implemented or does nothing, returning\n");
852 return;
853}
854
855// ----------------------------------------------------------------------------
856
857static void
858android_mtp_MtpDatabase_setup()
859{
860 MyMtpDatabase* database = new MyMtpDatabase();
861}
862
863static void
864android_mtp_MtpDatabase_finalize()
865{
866 return;
867}
868
869static std::string
870android_mtp_MtpPropertyGroup_format_date_time(long seconds)
871{
872 char date[20];
873 formatDateTime(seconds, date, sizeof(date));
874 return date;
875}
876
877void MyMtpDatabase::lockMutex(void) {
878 std::map<int, MtpStorage*>::iterator storit;
879 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
880 storit->second->lockMutex(0);
881 }
882}
883
884void MyMtpDatabase::unlockMutex(void) {
885 std::map<int, MtpStorage*>::iterator storit;
886 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
887 storit->second->unlockMutex(0);
888 }
889}