Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: src/libmtp.c

Issue 2364793002: Revert "Uprev libmtp to 1.1.12" (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/libmtp@master
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/libmtp.h ('k') | src/libmtp.sym » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /** 1 /**
2 * \file libmtp.c 2 * \file libmtp.c
3 * 3 *
4 * Copyright (C) 2005-2011 Linus Walleij <triad@df.lth.se> 4 * Copyright (C) 2005-2011 Linus Walleij <triad@df.lth.se>
5 * Copyright (C) 2005-2008 Richard A. Low <richard@wentnet.com> 5 * Copyright (C) 2005-2008 Richard A. Low <richard@wentnet.com>
6 * Copyright (C) 2007 Ted Bullock <tbullock@canada.com> 6 * Copyright (C) 2007 Ted Bullock <tbullock@canada.com>
7 * Copyright (C) 2007 Tero Saarni <tero.saarni@gmail.com> 7 * Copyright (C) 2007 Tero Saarni <tero.saarni@gmail.com>
8 * Copyright (C) 2008 Florent Mertens <flomertens@gmail.com> 8 * Copyright (C) 2008 Florent Mertens <flomertens@gmail.com>
9 * 9 *
10 * This library is free software; you can redistribute it and/or 10 * This library is free software; you can redistribute it and/or
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 * otherwise the libmtp.h device has to be dependent on ptp.h 109 * otherwise the libmtp.h device has to be dependent on ptp.h
110 * to be installed too, and we don't want that. 110 * to be installed too, and we don't want that.
111 */ 111 */
112 typedef struct propertymap_struct { 112 typedef struct propertymap_struct {
113 char *description; /**< Text description for the property */ 113 char *description; /**< Text description for the property */
114 LIBMTP_property_t id; /**< LIBMTP internal type for the property */ 114 LIBMTP_property_t id; /**< LIBMTP internal type for the property */
115 uint16_t ptp_id; /**< PTP ID for the property */ 115 uint16_t ptp_id; /**< PTP ID for the property */
116 struct propertymap_struct *next; 116 struct propertymap_struct *next;
117 } propertymap_t; 117 } propertymap_t;
118 118
119 /*
120 * This is a simple container for holding our callback and user_data
121 * for parsing onwards to the usb_event_async function.
122 */
123 typedef struct event_cb_data_struct {
124 LIBMTP_event_cb_fn cb;
125 void *user_data;
126 } event_cb_data_t;
127
128 // Global variables 119 // Global variables
129 // This holds the global filetype mapping table 120 // This holds the global filetype mapping table
130 static filemap_t *g_filemap = NULL; 121 static filemap_t *filemap = NULL;
131 // This holds the global property mapping table 122 // This holds the global property mapping table
132 static propertymap_t *g_propertymap = NULL; 123 static propertymap_t *propertymap = NULL;
133 124
134 /* 125 /*
135 * Forward declarations of local (static) functions. 126 * Forward declarations of local (static) functions.
136 */ 127 */
137 static int register_filetype(char const * const description, LIBMTP_filetype_t c onst id, 128 static int register_filetype(char const * const description, LIBMTP_filetype_t c onst id,
138 uint16_t const ptp_id); 129 uint16_t const ptp_id);
139 static void init_filemap(); 130 static void init_filemap();
140 static int register_property(char const * const description, LIBMTP_property_t c onst id, 131 static int register_property(char const * const description, LIBMTP_property_t c onst id,
141 uint16_t const ptp_id); 132 uint16_t const ptp_id);
142 static void init_propertymap(); 133 static void init_propertymap();
143 static void add_error_to_errorstack(LIBMTP_mtpdevice_t *device, 134 static void add_error_to_errorstack(LIBMTP_mtpdevice_t *device,
144 LIBMTP_error_number_t errornumber, 135 LIBMTP_error_number_t errornumber,
145 char const * const error_text); 136 char const * const error_text);
146 static void add_ptp_error_to_errorstack(LIBMTP_mtpdevice_t *device, 137 static void add_ptp_error_to_errorstack(LIBMTP_mtpdevice_t *device,
147 uint16_t ptp_error, 138 uint16_t ptp_error,
148 char const * const error_text); 139 char const * const error_text);
149 static void flush_handles(LIBMTP_mtpdevice_t *device); 140 static void flush_handles(LIBMTP_mtpdevice_t *device);
150 static void get_handles_recursively(LIBMTP_mtpdevice_t *device, 141 static void get_handles_recursively(LIBMTP_mtpdevice_t *device,
151 PTPParams *params, 142 PTPParams *params,
152 uint32_t storageid, 143 uint32_t storageid,
153 uint32_t parent); 144 uint32_t parent);
154 static void free_storage_list(LIBMTP_mtpdevice_t *device); 145 static void free_storage_list(LIBMTP_mtpdevice_t *device);
155 static int sort_storage_by(LIBMTP_mtpdevice_t *device, int const sortby); 146 static int sort_storage_by(LIBMTP_mtpdevice_t *device, int const sortby);
156 static uint32_t get_writeable_storageid(LIBMTP_mtpdevice_t *device, 147 static uint32_t get_writeable_storageid(LIBMTP_mtpdevice_t *device, uint64_t fit size);
157 » » » » » uint64_t fitsize);
158 static int get_storage_freespace(LIBMTP_mtpdevice_t *device, 148 static int get_storage_freespace(LIBMTP_mtpdevice_t *device,
159 LIBMTP_devicestorage_t *storage, 149 LIBMTP_devicestorage_t *storage,
160 uint64_t *freespace); 150 uint64_t *freespace);
161 static int check_if_file_fits(LIBMTP_mtpdevice_t *device, 151 static int check_if_file_fits(LIBMTP_mtpdevice_t *device,
162 LIBMTP_devicestorage_t *storage, 152 LIBMTP_devicestorage_t *storage,
163 uint64_t const filesize); 153 uint64_t const filesize);
164 static uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype); 154 static uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype);
165 static LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype); 155 static LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype);
166 static uint16_t map_libmtp_property_to_ptp_property(LIBMTP_property_t inproperty ); 156 static uint16_t map_libmtp_property_to_ptp_property(LIBMTP_property_t inproperty );
167 static LIBMTP_property_t map_ptp_property_to_libmtp_property(uint16_t intype); 157 static LIBMTP_property_t map_ptp_property_to_libmtp_property(uint16_t intype);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 uint32_t const no_tracks); 204 uint32_t const no_tracks);
215 static int send_file_object_info(LIBMTP_mtpdevice_t *device, LIBMTP_file_t *file data); 205 static int send_file_object_info(LIBMTP_mtpdevice_t *device, LIBMTP_file_t *file data);
216 static void add_object_to_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id); 206 static void add_object_to_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id);
217 static void update_metadata_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id ); 207 static void update_metadata_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id );
218 static int set_object_filename(LIBMTP_mtpdevice_t *device, 208 static int set_object_filename(LIBMTP_mtpdevice_t *device,
219 uint32_t object_id, 209 uint32_t object_id,
220 uint16_t ptp_type, 210 uint16_t ptp_type,
221 const char **newname); 211 const char **newname);
222 static char *generate_unique_filename(PTPParams* params, char const * const file name); 212 static char *generate_unique_filename(PTPParams* params, char const * const file name);
223 static int check_filename_exists(PTPParams* params, char const * const filename) ; 213 static int check_filename_exists(PTPParams* params, char const * const filename) ;
224 static void LIBMTP_Handle_Event(PTPContainer *ptp_event,
225 LIBMTP_event_t *event, uint32_t *out1);
226 214
227 /** 215 /**
228 * These are to wrap the get/put handlers to convert from the MTP types to PTP t ypes 216 * These are to wrap the get/put handlers to convert from the MTP types to PTP t ypes
229 * in a reliable way 217 * in a reliable way
230 */ 218 */
231 typedef struct _MTPDataHandler { 219 typedef struct _MTPDataHandler {
232 MTPDataGetFunc getfunc; 220 MTPDataGetFunc getfunc;
233 MTPDataPutFunc putfunc; 221 MTPDataPutFunc putfunc;
234 void *priv; 222 void *priv;
235 } MTPDataHandler; 223 } MTPDataHandler;
236 224
237 static uint16_t get_func_wrapper(PTPParams* params, void* priv, unsigned long wa ntlen, unsigned char *data, unsigned long *gotlen); 225 static uint16_t get_func_wrapper(PTPParams* params, void* priv, unsigned long wa ntlen, unsigned char *data, unsigned long *gotlen);
238 static uint16_t put_func_wrapper(PTPParams* params, void* priv, unsigned long se ndlen, unsigned char *data); 226 static uint16_t put_func_wrapper(PTPParams* params, void* priv, unsigned long se ndlen, unsigned char *data, unsigned long *putlen);
239 227
240 /** 228 /**
241 * Checks if a filename ends with ".ogg". Used in various 229 * Checks if a filename ends with ".ogg". Used in various
242 * situations when the device has no idea that it support 230 * situations when the device has no idea that it support
243 * OGG but still does. 231 * OGG but still does.
244 * 232 *
245 * @param name string to be checked. 233 * @param name string to be checked.
246 * @return 0 if this does not end with ogg, any other 234 * @return 0 if this does not end with ogg, any other
247 * value means it does. 235 * value means it does.
248 */ 236 */
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 * @param id libmtp internal filetype id 298 * @param id libmtp internal filetype id
311 * @param ptp_id PTP filetype id 299 * @param ptp_id PTP filetype id
312 * @return 0 for success any other value means error. 300 * @return 0 for success any other value means error.
313 */ 301 */
314 static int register_filetype(char const * const description, LIBMTP_filetype_t c onst id, 302 static int register_filetype(char const * const description, LIBMTP_filetype_t c onst id,
315 uint16_t const ptp_id) 303 uint16_t const ptp_id)
316 { 304 {
317 filemap_t *new = NULL, *current; 305 filemap_t *new = NULL, *current;
318 306
319 // Has this LIBMTP filetype been registered before ? 307 // Has this LIBMTP filetype been registered before ?
320 current = g_filemap; 308 current = filemap;
321 while (current != NULL) { 309 while (current != NULL) {
322 if(current->id == id) { 310 if(current->id == id) {
323 break; 311 break;
324 } 312 }
325 current = current->next; 313 current = current->next;
326 } 314 }
327 315
328 // Create the entry 316 // Create the entry
329 if(current == NULL) { 317 if(current == NULL) {
330 new = new_filemap_entry(); 318 new = new_filemap_entry();
331 if(new == NULL) { 319 if(new == NULL) {
332 return 1; 320 return 1;
333 } 321 }
334 322
335 new->id = id; 323 new->id = id;
336 if(description != NULL) { 324 if(description != NULL) {
337 new->description = strdup(description); 325 new->description = strdup(description);
338 } 326 }
339 new->ptp_id = ptp_id; 327 new->ptp_id = ptp_id;
340 328
341 // Add the entry to the list 329 // Add the entry to the list
342 if(g_filemap == NULL) { 330 if(filemap == NULL) {
343 g_filemap = new; 331 filemap = new;
344 } else { 332 } else {
345 current = g_filemap; 333 current = filemap;
346 while (current->next != NULL ) current=current->next; 334 while (current->next != NULL ) current=current->next;
347 current->next = new; 335 current->next = new;
348 } 336 }
349 // Update the existing entry 337 // Update the existing entry
350 } else { 338 } else {
351 if (current->description != NULL) { 339 if (current->description != NULL) {
352 free(current->description); 340 free(current->description);
353 } 341 }
354 current->description = NULL; 342 current->description = NULL;
355 if(description != NULL) { 343 if(description != NULL) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 400
413 /** 401 /**
414 * Returns the PTP filetype that maps to a certain libmtp internal file type. 402 * Returns the PTP filetype that maps to a certain libmtp internal file type.
415 * @param intype the MTP library interface type 403 * @param intype the MTP library interface type
416 * @return the PTP (libgphoto2) interface type 404 * @return the PTP (libgphoto2) interface type
417 */ 405 */
418 static uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype) 406 static uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype)
419 { 407 {
420 filemap_t *current; 408 filemap_t *current;
421 409
422 current = g_filemap; 410 current = filemap;
423 411
424 while (current != NULL) { 412 while (current != NULL) {
425 if(current->id == intype) { 413 if(current->id == intype) {
426 return current->ptp_id; 414 return current->ptp_id;
427 } 415 }
428 current = current->next; 416 current = current->next;
429 } 417 }
430 // printf("map_libmtp_type_to_ptp_type: unknown filetype.\n"); 418 // printf("map_libmtp_type_to_ptp_type: unknown filetype.\n");
431 return PTP_OFC_Undefined; 419 return PTP_OFC_Undefined;
432 } 420 }
433 421
434 422
435 /** 423 /**
436 * Returns the MTP internal interface type that maps to a certain ptp 424 * Returns the MTP internal interface type that maps to a certain ptp
437 * interface type. 425 * interface type.
438 * @param intype the PTP (libgphoto2) interface type 426 * @param intype the PTP (libgphoto2) interface type
439 * @return the MTP library interface type 427 * @return the MTP library interface type
440 */ 428 */
441 static LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype) 429 static LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype)
442 { 430 {
443 filemap_t *current; 431 filemap_t *current;
444 432
445 current = g_filemap; 433 current = filemap;
446 434
447 while (current != NULL) { 435 while (current != NULL) {
448 if(current->ptp_id == intype) { 436 if(current->ptp_id == intype) {
449 return current->id; 437 return current->id;
450 } 438 }
451 current = current->next; 439 current = current->next;
452 } 440 }
453 // printf("map_ptp_type_to_libmtp_type: unknown filetype.\n"); 441 // printf("map_ptp_type_to_libmtp_type: unknown filetype.\n");
454 return LIBMTP_FILETYPE_UNKNOWN; 442 return LIBMTP_FILETYPE_UNKNOWN;
455 } 443 }
(...skipping 25 matching lines...) Expand all
481 * @param id libmtp internal property id 469 * @param id libmtp internal property id
482 * @param ptp_id PTP property id 470 * @param ptp_id PTP property id
483 * @return 0 for success any other value means error. 471 * @return 0 for success any other value means error.
484 */ 472 */
485 static int register_property(char const * const description, LIBMTP_property_t c onst id, 473 static int register_property(char const * const description, LIBMTP_property_t c onst id,
486 uint16_t const ptp_id) 474 uint16_t const ptp_id)
487 { 475 {
488 propertymap_t *new = NULL, *current; 476 propertymap_t *new = NULL, *current;
489 477
490 // Has this LIBMTP propety been registered before ? 478 // Has this LIBMTP propety been registered before ?
491 current = g_propertymap; 479 current = propertymap;
492 while (current != NULL) { 480 while (current != NULL) {
493 if(current->id == id) { 481 if(current->id == id) {
494 break; 482 break;
495 } 483 }
496 current = current->next; 484 current = current->next;
497 } 485 }
498 486
499 // Create the entry 487 // Create the entry
500 if(current == NULL) { 488 if(current == NULL) {
501 new = new_propertymap_entry(); 489 new = new_propertymap_entry();
502 if(new == NULL) { 490 if(new == NULL) {
503 return 1; 491 return 1;
504 } 492 }
505 493
506 new->id = id; 494 new->id = id;
507 if(description != NULL) { 495 if(description != NULL) {
508 new->description = strdup(description); 496 new->description = strdup(description);
509 } 497 }
510 new->ptp_id = ptp_id; 498 new->ptp_id = ptp_id;
511 499
512 // Add the entry to the list 500 // Add the entry to the list
513 if(g_propertymap == NULL) { 501 if(propertymap == NULL) {
514 g_propertymap = new; 502 propertymap = new;
515 } else { 503 } else {
516 current = g_propertymap; 504 current = propertymap;
517 while (current->next != NULL ) current=current->next; 505 while (current->next != NULL ) current=current->next;
518 current->next = new; 506 current->next = new;
519 } 507 }
520 // Update the existing entry 508 // Update the existing entry
521 } else { 509 } else {
522 if (current->description != NULL) { 510 if (current->description != NULL) {
523 free(current->description); 511 free(current->description);
524 } 512 }
525 current->description = NULL; 513 current->description = NULL;
526 if(description != NULL) { 514 if(description != NULL) {
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 694
707 /** 695 /**
708 * Returns the PTP property that maps to a certain libmtp internal property type . 696 * Returns the PTP property that maps to a certain libmtp internal property type .
709 * @param inproperty the MTP library interface property 697 * @param inproperty the MTP library interface property
710 * @return the PTP (libgphoto2) property type 698 * @return the PTP (libgphoto2) property type
711 */ 699 */
712 static uint16_t map_libmtp_property_to_ptp_property(LIBMTP_property_t inproperty ) 700 static uint16_t map_libmtp_property_to_ptp_property(LIBMTP_property_t inproperty )
713 { 701 {
714 propertymap_t *current; 702 propertymap_t *current;
715 703
716 current = g_propertymap; 704 current = propertymap;
717 705
718 while (current != NULL) { 706 while (current != NULL) {
719 if(current->id == inproperty) { 707 if(current->id == inproperty) {
720 return current->ptp_id; 708 return current->ptp_id;
721 } 709 }
722 current = current->next; 710 current = current->next;
723 } 711 }
724 return 0; 712 return 0;
725 } 713 }
726 714
727 715
728 /** 716 /**
729 * Returns the MTP internal interface property that maps to a certain ptp 717 * Returns the MTP internal interface property that maps to a certain ptp
730 * interface property. 718 * interface property.
731 * @param inproperty the PTP (libgphoto2) interface property 719 * @param inproperty the PTP (libgphoto2) interface property
732 * @return the MTP library interface property 720 * @return the MTP library interface property
733 */ 721 */
734 static LIBMTP_property_t map_ptp_property_to_libmtp_property(uint16_t inproperty ) 722 static LIBMTP_property_t map_ptp_property_to_libmtp_property(uint16_t inproperty )
735 { 723 {
736 propertymap_t *current; 724 propertymap_t *current;
737 725
738 current = g_propertymap; 726 current = propertymap;
739 727
740 while (current != NULL) { 728 while (current != NULL) {
741 if(current->ptp_id == inproperty) { 729 if(current->ptp_id == inproperty) {
742 return current->id; 730 return current->id;
743 } 731 }
744 current = current->next; 732 current = current->next;
745 } 733 }
746 // printf("map_ptp_type_to_libmtp_type: unknown filetype.\n"); 734 // printf("map_ptp_type_to_libmtp_type: unknown filetype.\n");
747 return LIBMTP_PROPERTY_UNKNOWN; 735 return LIBMTP_PROPERTY_UNKNOWN;
748 } 736 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
801 * This helper function returns a textual description for a libmtp 789 * This helper function returns a textual description for a libmtp
802 * file type to be used in dialog boxes etc. 790 * file type to be used in dialog boxes etc.
803 * @param intype the libmtp internal filetype to get a description for. 791 * @param intype the libmtp internal filetype to get a description for.
804 * @return a string representing the filetype, this must <b>NOT</b> 792 * @return a string representing the filetype, this must <b>NOT</b>
805 * be free():ed by the caller! 793 * be free():ed by the caller!
806 */ 794 */
807 char const * LIBMTP_Get_Filetype_Description(LIBMTP_filetype_t intype) 795 char const * LIBMTP_Get_Filetype_Description(LIBMTP_filetype_t intype)
808 { 796 {
809 filemap_t *current; 797 filemap_t *current;
810 798
811 current = g_filemap; 799 current = filemap;
812 800
813 while (current != NULL) { 801 while (current != NULL) {
814 if(current->id == intype) { 802 if(current->id == intype) {
815 return current->description; 803 return current->description;
816 } 804 }
817 current = current->next; 805 current = current->next;
818 } 806 }
819 807
820 return "Unknown filetype"; 808 return "Unknown filetype";
821 } 809 }
822 810
823 /** 811 /**
824 * This helper function returns a textual description for a libmtp 812 * This helper function returns a textual description for a libmtp
825 * property to be used in dialog boxes etc. 813 * property to be used in dialog boxes etc.
826 * @param inproperty the libmtp internal property to get a description for. 814 * @param inproperty the libmtp internal property to get a description for.
827 * @return a string representing the filetype, this must <b>NOT</b> 815 * @return a string representing the filetype, this must <b>NOT</b>
828 * be free():ed by the caller! 816 * be free():ed by the caller!
829 */ 817 */
830 char const * LIBMTP_Get_Property_Description(LIBMTP_property_t inproperty) 818 char const * LIBMTP_Get_Property_Description(LIBMTP_property_t inproperty)
831 { 819 {
832 propertymap_t *current; 820 propertymap_t *current;
833 821
834 current = g_propertymap; 822 current = propertymap;
835 823
836 while (current != NULL) { 824 while (current != NULL) {
837 if(current->id == inproperty) { 825 if(current->id == inproperty) {
838 return current->description; 826 return current->description;
839 } 827 }
840 current = current->next; 828 current = current->next;
841 } 829 }
842 830
843 return "Unknown property"; 831 return "Unknown property";
844 } 832 }
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
1333 * @param attribute_id PTP attribute ID 1321 * @param attribute_id PTP attribute ID
1334 * @return valid string or NULL on failure. The returned string 1322 * @return valid string or NULL on failure. The returned string
1335 * must bee <code>free()</code>:ed by the caller after 1323 * must bee <code>free()</code>:ed by the caller after
1336 * use. 1324 * use.
1337 */ 1325 */
1338 static char *get_string_from_object(LIBMTP_mtpdevice_t *device, uint32_t const o bject_id, 1326 static char *get_string_from_object(LIBMTP_mtpdevice_t *device, uint32_t const o bject_id,
1339 uint16_t const attribute_id) 1327 uint16_t const attribute_id)
1340 { 1328 {
1341 PTPPropertyValue propval; 1329 PTPPropertyValue propval;
1342 char *retstring = NULL; 1330 char *retstring = NULL;
1343 PTPParams *params; 1331 PTPParams *params = (PTPParams *) device->params;
1344 uint16_t ret; 1332 uint16_t ret;
1345 MTPProperties *prop; 1333 MTPProperties *prop;
1346 1334
1347 if (!device || !object_id) 1335 if ( device == NULL || object_id == 0) {
1348 return NULL; 1336 return NULL;
1349 1337 }
1350 params = (PTPParams *) device->params;
1351 1338
1352 prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id); 1339 prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
1353 if (prop) { 1340 if (prop) {
1354 if (prop->propval.str != NULL) 1341 if (prop->propval.str != NULL)
1355 return strdup(prop->propval.str); 1342 return strdup(prop->propval.str);
1356 else 1343 else
1357 return NULL; 1344 return NULL;
1358 } 1345 }
1359 1346
1360 ret = ptp_mtp_getobjectpropvalue(params, object_id, attribute_id, &propval, PT P_DTC_STR); 1347 ret = ptp_mtp_getobjectpropvalue(params, object_id, attribute_id, &propval, PT P_DTC_STR);
(...skipping 16 matching lines...) Expand all
1377 * @param object_id Object reference 1364 * @param object_id Object reference
1378 * @param attribute_id PTP attribute ID 1365 * @param attribute_id PTP attribute ID
1379 * @param value_default Default value to return on failure 1366 * @param value_default Default value to return on failure
1380 * @return the value 1367 * @return the value
1381 */ 1368 */
1382 static uint64_t get_u64_from_object(LIBMTP_mtpdevice_t *device,uint32_t const ob ject_id, 1369 static uint64_t get_u64_from_object(LIBMTP_mtpdevice_t *device,uint32_t const ob ject_id,
1383 uint16_t const attribute_id, uint64_t const value_default) 1370 uint16_t const attribute_id, uint64_t const value_default)
1384 { 1371 {
1385 PTPPropertyValue propval; 1372 PTPPropertyValue propval;
1386 uint64_t retval = value_default; 1373 uint64_t retval = value_default;
1387 PTPParams *params; 1374 PTPParams *params = (PTPParams *) device->params;
1388 uint16_t ret; 1375 uint16_t ret;
1389 MTPProperties *prop; 1376 MTPProperties *prop;
1390 1377
1391 if (!device) 1378 if ( device == NULL ) {
1392 return value_default; 1379 return value_default;
1393 1380 }
1394 params = (PTPParams *) device->params;
1395 1381
1396 prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id); 1382 prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
1397 if (prop) 1383 if (prop)
1398 return prop->propval.u64; 1384 return prop->propval.u64;
1399 1385
1400 ret = ptp_mtp_getobjectpropvalue(params, object_id, 1386 ret = ptp_mtp_getobjectpropvalue(params, object_id,
1401 attribute_id, 1387 attribute_id,
1402 &propval, 1388 &propval,
1403 PTP_DTC_UINT64); 1389 PTP_DTC_UINT64);
1404 if (ret == PTP_RC_OK) { 1390 if (ret == PTP_RC_OK) {
(...skipping 12 matching lines...) Expand all
1417 * @param object_id Object reference 1403 * @param object_id Object reference
1418 * @param attribute_id PTP attribute ID 1404 * @param attribute_id PTP attribute ID
1419 * @param value_default Default value to return on failure 1405 * @param value_default Default value to return on failure
1420 * @return the value 1406 * @return the value
1421 */ 1407 */
1422 static uint32_t get_u32_from_object(LIBMTP_mtpdevice_t *device,uint32_t const ob ject_id, 1408 static uint32_t get_u32_from_object(LIBMTP_mtpdevice_t *device,uint32_t const ob ject_id,
1423 uint16_t const attribute_id, uint32_t const value_default) 1409 uint16_t const attribute_id, uint32_t const value_default)
1424 { 1410 {
1425 PTPPropertyValue propval; 1411 PTPPropertyValue propval;
1426 uint32_t retval = value_default; 1412 uint32_t retval = value_default;
1427 PTPParams *params; 1413 PTPParams *params = (PTPParams *) device->params;
1428 uint16_t ret; 1414 uint16_t ret;
1429 MTPProperties *prop; 1415 MTPProperties *prop;
1430 1416
1431 if (!device) 1417 if ( device == NULL ) {
1432 return value_default; 1418 return value_default;
1433 1419 }
1434 params = (PTPParams *) device->params;
1435 1420
1436 prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id); 1421 prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
1437 if (prop) 1422 if (prop)
1438 return prop->propval.u32; 1423 return prop->propval.u32;
1439 1424
1440 ret = ptp_mtp_getobjectpropvalue(params, object_id, 1425 ret = ptp_mtp_getobjectpropvalue(params, object_id,
1441 attribute_id, 1426 attribute_id,
1442 &propval, 1427 &propval,
1443 PTP_DTC_UINT32); 1428 PTP_DTC_UINT32);
1444 if (ret == PTP_RC_OK) { 1429 if (ret == PTP_RC_OK) {
(...skipping 11 matching lines...) Expand all
1456 * @param object_id Object reference 1441 * @param object_id Object reference
1457 * @param attribute_id PTP attribute ID 1442 * @param attribute_id PTP attribute ID
1458 * @param value_default Default value to return on failure 1443 * @param value_default Default value to return on failure
1459 * @return a value 1444 * @return a value
1460 */ 1445 */
1461 static uint16_t get_u16_from_object(LIBMTP_mtpdevice_t *device, uint32_t const o bject_id, 1446 static uint16_t get_u16_from_object(LIBMTP_mtpdevice_t *device, uint32_t const o bject_id,
1462 uint16_t const attribute_id, uint16_t const value_default) 1447 uint16_t const attribute_id, uint16_t const value_default)
1463 { 1448 {
1464 PTPPropertyValue propval; 1449 PTPPropertyValue propval;
1465 uint16_t retval = value_default; 1450 uint16_t retval = value_default;
1466 PTPParams *params; 1451 PTPParams *params = (PTPParams *) device->params;
1467 uint16_t ret; 1452 uint16_t ret;
1468 MTPProperties *prop; 1453 MTPProperties *prop;
1469 1454
1470 if (!device) 1455 if ( device == NULL ) {
1471 return value_default; 1456 return value_default;
1472 1457 }
1473 params = (PTPParams *) device->params;
1474 1458
1475 // This O(n) search should not be used so often, since code 1459 // This O(n) search should not be used so often, since code
1476 // using the cached properties don't usually call this function. 1460 // using the cached properties don't usually call this function.
1477 prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id); 1461 prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
1478 if (prop) 1462 if (prop)
1479 return prop->propval.u16; 1463 return prop->propval.u16;
1480 1464
1481 ret = ptp_mtp_getobjectpropvalue(params, object_id, 1465 ret = ptp_mtp_getobjectpropvalue(params, object_id,
1482 attribute_id, 1466 attribute_id,
1483 &propval, 1467 &propval,
(...skipping 14 matching lines...) Expand all
1498 * @param object_id Object reference 1482 * @param object_id Object reference
1499 * @param attribute_id PTP attribute ID 1483 * @param attribute_id PTP attribute ID
1500 * @param value_default Default value to return on failure 1484 * @param value_default Default value to return on failure
1501 * @return a value 1485 * @return a value
1502 */ 1486 */
1503 static uint8_t get_u8_from_object(LIBMTP_mtpdevice_t *device, uint32_t const obj ect_id, 1487 static uint8_t get_u8_from_object(LIBMTP_mtpdevice_t *device, uint32_t const obj ect_id,
1504 uint16_t const attribute_id, uint8_t const val ue_default) 1488 uint16_t const attribute_id, uint8_t const val ue_default)
1505 { 1489 {
1506 PTPPropertyValue propval; 1490 PTPPropertyValue propval;
1507 uint8_t retval = value_default; 1491 uint8_t retval = value_default;
1508 PTPParams *params; 1492 PTPParams *params = (PTPParams *) device->params;
1509 uint16_t ret; 1493 uint16_t ret;
1510 MTPProperties *prop; 1494 MTPProperties *prop;
1511 1495
1512 if (!device) 1496 if ( device == NULL ) {
1513 return value_default; 1497 return value_default;
1514 1498 }
1515 params = (PTPParams *) device->params;
1516 1499
1517 // This O(n) search should not be used so often, since code 1500 // This O(n) search should not be used so often, since code
1518 // using the cached properties don't usually call this function. 1501 // using the cached properties don't usually call this function.
1519 prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id); 1502 prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
1520 if (prop) 1503 if (prop)
1521 return prop->propval.u8; 1504 return prop->propval.u8;
1522 1505
1523 ret = ptp_mtp_getobjectpropvalue(params, object_id, 1506 ret = ptp_mtp_getobjectpropvalue(params, object_id,
1524 attribute_id, 1507 attribute_id,
1525 &propval, 1508 &propval,
(...skipping 13 matching lines...) Expand all
1539 * @param device a pointer to an MTP device. 1522 * @param device a pointer to an MTP device.
1540 * @param object_id Object reference 1523 * @param object_id Object reference
1541 * @param attribute_id PTP attribute ID 1524 * @param attribute_id PTP attribute ID
1542 * @param string string value to set 1525 * @param string string value to set
1543 * @return 0 on success, any other value means failure 1526 * @return 0 on success, any other value means failure
1544 */ 1527 */
1545 static int set_object_string(LIBMTP_mtpdevice_t *device, uint32_t const object_i d, 1528 static int set_object_string(LIBMTP_mtpdevice_t *device, uint32_t const object_i d,
1546 uint16_t const attribute_id, char const * const str ing) 1529 uint16_t const attribute_id, char const * const str ing)
1547 { 1530 {
1548 PTPPropertyValue propval; 1531 PTPPropertyValue propval;
1549 PTPParams *params; 1532 PTPParams *params = (PTPParams *) device->params;
1550 uint16_t ret; 1533 uint16_t ret;
1551 1534
1552 if (!device || !string) 1535 if (device == NULL || string == NULL) {
1553 return -1; 1536 return -1;
1554 1537 }
1555 params = (PTPParams *) device->params;
1556 1538
1557 if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) { 1539 if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
1558 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_string(): could not set object string: " 1540 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_string(): could not set object string: "
1559 "PTP_OC_MTP_SetObjectPropValue not supported."); 1541 "PTP_OC_MTP_SetObjectPropValue not supported.");
1560 return -1; 1542 return -1;
1561 } 1543 }
1562 propval.str = (char *) string; 1544 propval.str = (char *) string;
1563 ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PT P_DTC_STR); 1545 ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PT P_DTC_STR);
1564 if (ret != PTP_RC_OK) { 1546 if (ret != PTP_RC_OK) {
1565 add_ptp_error_to_errorstack(device, ret, "set_object_string(): could not set object string."); 1547 add_ptp_error_to_errorstack(device, ret, "set_object_string(): could not set object string.");
(...skipping 10 matching lines...) Expand all
1576 * @param device a pointer to an MTP device. 1558 * @param device a pointer to an MTP device.
1577 * @param object_id Object reference 1559 * @param object_id Object reference
1578 * @param attribute_id PTP attribute ID 1560 * @param attribute_id PTP attribute ID
1579 * @param value 32-bit unsigned integer to set 1561 * @param value 32-bit unsigned integer to set
1580 * @return 0 on success, any other value means failure 1562 * @return 0 on success, any other value means failure
1581 */ 1563 */
1582 static int set_object_u32(LIBMTP_mtpdevice_t *device, uint32_t const object_id, 1564 static int set_object_u32(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1583 uint16_t const attribute_id, uint32_t const value) 1565 uint16_t const attribute_id, uint32_t const value)
1584 { 1566 {
1585 PTPPropertyValue propval; 1567 PTPPropertyValue propval;
1586 PTPParams *params; 1568 PTPParams *params = (PTPParams *) device->params;
1587 uint16_t ret; 1569 uint16_t ret;
1588 1570
1589 if (!device) 1571 if (device == NULL) {
1590 return -1; 1572 return -1;
1591 1573 }
1592 params = (PTPParams *) device->params;
1593 1574
1594 if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) { 1575 if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
1595 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_u32(): cou ld not set unsigned 32bit integer property: " 1576 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_u32(): cou ld not set unsigned 32bit integer property: "
1596 "PTP_OC_MTP_SetObjectPropValue not supported."); 1577 "PTP_OC_MTP_SetObjectPropValue not supported.");
1597 return -1; 1578 return -1;
1598 } 1579 }
1599 1580
1600 propval.u32 = value; 1581 propval.u32 = value;
1601 ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PT P_DTC_UINT32); 1582 ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PT P_DTC_UINT32);
1602 if (ret != PTP_RC_OK) { 1583 if (ret != PTP_RC_OK) {
(...skipping 10 matching lines...) Expand all
1613 * @param device a pointer to an MTP device. 1594 * @param device a pointer to an MTP device.
1614 * @param object_id Object reference 1595 * @param object_id Object reference
1615 * @param attribute_id PTP attribute ID 1596 * @param attribute_id PTP attribute ID
1616 * @param value 16-bit unsigned integer to set 1597 * @param value 16-bit unsigned integer to set
1617 * @return 0 on success, any other value means failure 1598 * @return 0 on success, any other value means failure
1618 */ 1599 */
1619 static int set_object_u16(LIBMTP_mtpdevice_t *device, uint32_t const object_id, 1600 static int set_object_u16(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1620 uint16_t const attribute_id, uint16_t const value) 1601 uint16_t const attribute_id, uint16_t const value)
1621 { 1602 {
1622 PTPPropertyValue propval; 1603 PTPPropertyValue propval;
1623 PTPParams *params; 1604 PTPParams *params = (PTPParams *) device->params;
1624 uint16_t ret; 1605 uint16_t ret;
1625 1606
1626 if (!device) 1607 if (device == NULL) {
1627 return 1; 1608 return 1;
1628 1609 }
1629 params = (PTPParams *) device->params;
1630 1610
1631 if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) { 1611 if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
1632 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_u16(): cou ld not set unsigned 16bit integer property: " 1612 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_u16(): cou ld not set unsigned 16bit integer property: "
1633 "PTP_OC_MTP_SetObjectPropValue not supported."); 1613 "PTP_OC_MTP_SetObjectPropValue not supported.");
1634 return -1; 1614 return -1;
1635 } 1615 }
1636 propval.u16 = value; 1616 propval.u16 = value;
1637 ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PT P_DTC_UINT16); 1617 ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PT P_DTC_UINT16);
1638 if (ret != PTP_RC_OK) { 1618 if (ret != PTP_RC_OK) {
1639 add_ptp_error_to_errorstack(device, ret, "set_object_u16(): could not set un signed 16bit integer property."); 1619 add_ptp_error_to_errorstack(device, ret, "set_object_u16(): could not set un signed 16bit integer property.");
1640 return 1; 1620 return 1;
1641 } 1621 }
1642 1622
1643 return 0; 1623 return 0;
1644 } 1624 }
1645 1625
1646 /** 1626 /**
1647 * Sets an object attribute from an unsigned 8-bit integer 1627 * Sets an object attribute from an unsigned 8-bit integer
1648 * 1628 *
1649 * @param device a pointer to an MTP device. 1629 * @param device a pointer to an MTP device.
1650 * @param object_id Object reference 1630 * @param object_id Object reference
1651 * @param attribute_id PTP attribute ID 1631 * @param attribute_id PTP attribute ID
1652 * @param value 8-bit unsigned integer to set 1632 * @param value 8-bit unsigned integer to set
1653 * @return 0 on success, any other value means failure 1633 * @return 0 on success, any other value means failure
1654 */ 1634 */
1655 static int set_object_u8(LIBMTP_mtpdevice_t *device, uint32_t const object_id, 1635 static int set_object_u8(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1656 uint16_t const attribute_id, uint8_t const value) 1636 uint16_t const attribute_id, uint8_t const value)
1657 { 1637 {
1658 PTPPropertyValue propval; 1638 PTPPropertyValue propval;
1659 PTPParams *params; 1639 PTPParams *params = (PTPParams *) device->params;
1660 uint16_t ret; 1640 uint16_t ret;
1661 1641
1662 if (!device) 1642 if (device == NULL) {
1663 return 1; 1643 return 1;
1664 1644 }
1665 params = (PTPParams *) device->params;
1666 1645
1667 if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) { 1646 if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
1668 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_u8(): coul d not set unsigned 8bit integer property: " 1647 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_u8(): coul d not set unsigned 8bit integer property: "
1669 "PTP_OC_MTP_SetObjectPropValue not supported."); 1648 "PTP_OC_MTP_SetObjectPropValue not supported.");
1670 return -1; 1649 return -1;
1671 } 1650 }
1672 propval.u8 = value; 1651 propval.u8 = value;
1673 ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PT P_DTC_UINT8); 1652 ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PT P_DTC_UINT8);
1674 if (ret != PTP_RC_OK) { 1653 if (ret != PTP_RC_OK) {
1675 add_ptp_error_to_errorstack(device, ret, "set_object_u8(): could not set uns igned 8bit integer property."); 1654 add_ptp_error_to_errorstack(device, ret, "set_object_u8(): could not set uns igned 8bit integer property.");
(...skipping 14 matching lines...) Expand all
1690 LIBMTP_raw_device_t *devices; 1669 LIBMTP_raw_device_t *devices;
1691 int numdevs; 1670 int numdevs;
1692 LIBMTP_error_number_t ret; 1671 LIBMTP_error_number_t ret;
1693 1672
1694 ret = LIBMTP_Detect_Raw_Devices(&devices, &numdevs); 1673 ret = LIBMTP_Detect_Raw_Devices(&devices, &numdevs);
1695 if (ret != LIBMTP_ERROR_NONE) { 1674 if (ret != LIBMTP_ERROR_NONE) {
1696 return NULL; 1675 return NULL;
1697 } 1676 }
1698 1677
1699 if (devices == NULL || numdevs == 0) { 1678 if (devices == NULL || numdevs == 0) {
1700 free(devices);
1701 return NULL; 1679 return NULL;
1702 } 1680 }
1703 1681
1704 first_device = LIBMTP_Open_Raw_Device(&devices[0]); 1682 first_device = LIBMTP_Open_Raw_Device(&devices[0]);
1705 free(devices); 1683 free(devices);
1706 return first_device; 1684 return first_device;
1707 } 1685 }
1708 1686
1709 /** 1687 /**
1710 * Overriding debug function. 1688 * Overriding debug function.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1761 int start = 0; 1739 int start = 0;
1762 int end = 0; 1740 int end = 0;
1763 1741
1764 /* NULL on Canon A70 */ 1742 /* NULL on Canon A70 */
1765 if (!desc) 1743 if (!desc)
1766 return; 1744 return;
1767 1745
1768 /* descriptors are divided by semicolons */ 1746 /* descriptors are divided by semicolons */
1769 while (end < strlen(desc)) { 1747 while (end < strlen(desc)) {
1770 /* Skip past initial whitespace */ 1748 /* Skip past initial whitespace */
1771 while ((end < strlen(desc)) && (desc[start] == ' ' )) { 1749 while (desc[start] == ' ' && end < strlen(desc)) {
1772 start++; 1750 start++;
1773 end++; 1751 end++;
1774 } 1752 }
1775 /* Detect extension */ 1753 /* Detect extension */
1776 while ((end < strlen(desc)) && (desc[end] != ';')) 1754 while (desc[end] != ';' && end < strlen(desc))
1777 end++; 1755 end++;
1778 if (end < strlen(desc)) { 1756 if (end < strlen(desc)) {
1779 char *element = strndup(desc + start, end-start); 1757 char *element = strndup(desc + start, end-start);
1780 if (element) { 1758 if (element) {
1781 int i = 0; 1759 int i = 0;
1782 // printf(" Element: \"%s\"\n", element); 1760 // printf(" Element: \"%s\"\n", element);
1783 1761
1784 /* Parse for an extension */ 1762 /* Parse for an extension */
1785 while ((i < strlen(element)) && (element[i] != ':')) 1763 while (element[i] != ':' && i < strlen(element))
1786 i++; 1764 i++;
1787 if (i < strlen(element)) { 1765 if (i < strlen(element)) {
1788 char *name = strndup(element, i); 1766 char *name = strndup(element, i);
1789 int majstart = i+1; 1767 int majstart = i+1;
1790 // printf(" Extension: \"%s\"\n", name); 1768 // printf(" Extension: \"%s\"\n", name);
1791 1769
1792 /* Parse for minor/major punctuation mark for this extension */ 1770 /* Parse for minor/major punctuation mark for this extension */
1793 while ((i < strlen(element)) && (element[i] != '.')) 1771 while (element[i] != '.' && i < strlen(element))
1794 i++; 1772 i++;
1795 if (i > majstart && i < strlen(element)) { 1773 if (i > majstart && i < strlen(element)) {
1796 LIBMTP_device_extension_t *extension; 1774 LIBMTP_device_extension_t *extension;
1797 int major = 0; 1775 int major = 0;
1798 int minor = 0; 1776 int minor = 0;
1799 char *majorstr = strndup(element + majstart, i - majstart); 1777 char *majorstr = strndup(element + majstart, i - majstart);
1800 char *minorstr = strndup(element + i + 1, strlen(element) - i - 1); 1778 char *minorstr = strndup(element + i + 1, strlen(element) - i - 1);
1801 major = atoi(majorstr); 1779 major = atoi(majorstr);
1802 minor = atoi(minorstr); 1780 minor = atoi(minorstr);
1803 // printf(" Major: \"%s\" (parsed %d) Minor: \"%s\" (parsed %d)\n ",
1804 // majorstr, major, minorstr, minor);
1805 free(majorstr); 1781 free(majorstr);
1806 free(minorstr); 1782 free(minorstr);
1807 extension = malloc(sizeof(LIBMTP_device_extension_t)); 1783 extension = malloc(sizeof(LIBMTP_device_extension_t));
1808 extension->name = name; 1784 extension->name = name;
1809 extension->major = major; 1785 extension->major = major;
1810 extension->minor = minor; 1786 extension->minor = minor;
1811 extension->next = NULL; 1787 extension->next = NULL;
1812 if (mtpdevice->extensions == NULL) { 1788 if (mtpdevice->extensions == NULL) {
1813 mtpdevice->extensions = extension; 1789 mtpdevice->extensions = extension;
1814 } else { 1790 } else {
1815 LIBMTP_device_extension_t *tmp = mtpdevice->extensions; 1791 LIBMTP_device_extension_t *tmp = mtpdevice->extensions;
1816 while (tmp->next != NULL) 1792 while (tmp->next != NULL)
1817 tmp = tmp->next; 1793 tmp = tmp->next;
1818 tmp->next = extension; 1794 tmp->next = extension;
1819 } 1795 }
1796 // printf(" Major: \"%s\" (parsed %d) Minor: \"%s\" (parsed %d)\n ",
1797 // majorstr, major, minorstr, minor);
1820 } else { 1798 } else {
1821 LIBMTP_ERROR("LIBMTP ERROR: couldnt parse extension %s\n", 1799 LIBMTP_ERROR("LIBMTP ERROR: couldnt parse extension %s\n",
1822 element); 1800 element);
1823 } 1801 }
1824 } 1802 }
1825 free(element); 1803 free(element);
1826 } 1804 }
1827 } 1805 }
1828 end++; 1806 end++;
1829 start = end; 1807 start = end;
(...skipping 12 matching lines...) Expand all
1842 { 1820 {
1843 LIBMTP_mtpdevice_t *mtp_device; 1821 LIBMTP_mtpdevice_t *mtp_device;
1844 uint8_t bs = 0; 1822 uint8_t bs = 0;
1845 PTPParams *current_params; 1823 PTPParams *current_params;
1846 PTP_USB *ptp_usb; 1824 PTP_USB *ptp_usb;
1847 LIBMTP_error_number_t err; 1825 LIBMTP_error_number_t err;
1848 int i; 1826 int i;
1849 1827
1850 /* Allocate dynamic space for our device */ 1828 /* Allocate dynamic space for our device */
1851 mtp_device = (LIBMTP_mtpdevice_t *) malloc(sizeof(LIBMTP_mtpdevice_t)); 1829 mtp_device = (LIBMTP_mtpdevice_t *) malloc(sizeof(LIBMTP_mtpdevice_t));
1830 memset(mtp_device, 0, sizeof(LIBMTP_mtpdevice_t));
1852 /* Check if there was a memory allocation error */ 1831 /* Check if there was a memory allocation error */
1853 if(mtp_device == NULL) { 1832 if(mtp_device == NULL) {
1854 /* There has been an memory allocation error. We are going to ignore this 1833 /* There has been an memory allocation error. We are going to ignore this
1855 device and attempt to continue */ 1834 device and attempt to continue */
1856 1835
1857 /* TODO: This error statement could probably be a bit more robust */ 1836 /* TODO: This error statement could probably be a bit more robust */
1858 LIBMTP_ERROR("LIBMTP PANIC: connect_usb_devices encountered a memory " 1837 LIBMTP_ERROR("LIBMTP PANIC: connect_usb_devices encountered a memory "
1859 "allocation error with device %d on bus %d, trying to continue", 1838 "allocation error with device %d on bus %d, trying to continue",
1860 rawdevice->devnum, rawdevice->bus_location); 1839 rawdevice->devnum, rawdevice->bus_location);
1861 1840
1862 return NULL; 1841 return NULL;
1863 } 1842 }
1864 memset(mtp_device, 0, sizeof(LIBMTP_mtpdevice_t));
1865 // Non-cached by default 1843 // Non-cached by default
1866 mtp_device->cached = 0; 1844 mtp_device->cached = 0;
1867 1845
1868 /* Create PTP params */ 1846 /* Create PTP params */
1869 current_params = (PTPParams *) malloc(sizeof(PTPParams)); 1847 current_params = (PTPParams *) malloc(sizeof(PTPParams));
1870 if (current_params == NULL) { 1848 if (current_params == NULL) {
1871 free(mtp_device); 1849 free(mtp_device);
1872 return NULL; 1850 return NULL;
1873 } 1851 }
1874 memset(current_params, 0, sizeof(PTPParams)); 1852 memset(current_params, 0, sizeof(PTPParams));
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
2168 * FIXME: Potential race-condition here, if client deallocs device 2146 * FIXME: Potential race-condition here, if client deallocs device
2169 * while we're *not* waiting for input. As we'll be waiting for 2147 * while we're *not* waiting for input. As we'll be waiting for
2170 * input most of the time, it's unlikely but still worth considering 2148 * input most of the time, it's unlikely but still worth considering
2171 * for improvement. Also we cannot affect the state of the cache etc 2149 * for improvement. Also we cannot affect the state of the cache etc
2172 * unless we know we are the sole user on the device. A spinlock or 2150 * unless we know we are the sole user on the device. A spinlock or
2173 * mutex in the LIBMTP_mtpdevice_t is needed for this to work. 2151 * mutex in the LIBMTP_mtpdevice_t is needed for this to work.
2174 */ 2152 */
2175 PTPParams *params = (PTPParams *) device->params; 2153 PTPParams *params = (PTPParams *) device->params;
2176 PTPContainer ptp_event; 2154 PTPContainer ptp_event;
2177 uint16_t ret = ptp_usb_event_wait(params, &ptp_event); 2155 uint16_t ret = ptp_usb_event_wait(params, &ptp_event);
2156 uint16_t code;
2157 uint32_t session_id;
2158 uint32_t transaction_id;
2159 uint32_t param1;
2160 uint32_t param2;
2161 uint32_t param3;
2178 2162
2179 if (ret != PTP_RC_OK) { 2163 if (ret != PTP_RC_OK) {
2180 /* Device is closing down or other fatal stuff, exit thread */ 2164 /* Device is closing down or other fatal stuff, exit thread */
2181 return -1; 2165 return -1;
2182 } 2166 }
2183 LIBMTP_Handle_Event(&ptp_event, event, out1);
2184 return 0;
2185 }
2186
2187 void LIBMTP_Handle_Event(PTPContainer *ptp_event,
2188 LIBMTP_event_t *event, uint32_t *out1) {
2189 uint16_t code;
2190 uint32_t session_id;
2191 uint32_t param1;
2192 2167
2193 *event = LIBMTP_EVENT_NONE; 2168 *event = LIBMTP_EVENT_NONE;
2194 2169
2195 /* Process the event */ 2170 /* Process the event */
2196 code = ptp_event->Code; 2171 code = ptp_event.Code;
2197 session_id = ptp_event->SessionID; 2172 session_id = ptp_event.SessionID;
2198 param1 = ptp_event->Param1; 2173 transaction_id = ptp_event.Transaction_ID;
2174 param1 = ptp_event.Param1;
2175 param2 = ptp_event.Param2;
2176 param3 = ptp_event.Param3;
2199 2177
2200 switch(code) { 2178 switch(code) {
2201 case PTP_EC_Undefined: 2179 case PTP_EC_Undefined:
2202 LIBMTP_INFO("Received event PTP_EC_Undefined in session %u\n", session_id) ; 2180 LIBMTP_INFO("Received event PTP_EC_Undefined in session %u\n", session_id) ;
2203 break; 2181 break;
2204 case PTP_EC_CancelTransaction: 2182 case PTP_EC_CancelTransaction:
2205 LIBMTP_INFO("Received event PTP_EC_CancelTransaction in session %u\n", ses sion_id); 2183 LIBMTP_INFO("Received event PTP_EC_CancelTransaction in session %u\n", ses sion_id);
2206 break; 2184 break;
2207 case PTP_EC_ObjectAdded: 2185 case PTP_EC_ObjectAdded:
2208 LIBMTP_INFO("Received event PTP_EC_ObjectAdded in session %u\n", session_i d); 2186 LIBMTP_INFO("Received event PTP_EC_ObjectAdded in session %u\n", session_i d);
2209 *event = LIBMTP_EVENT_OBJECT_ADDED;
2210 *out1 = param1;
2211 break; 2187 break;
2212 case PTP_EC_ObjectRemoved: 2188 case PTP_EC_ObjectRemoved:
2213 LIBMTP_INFO("Received event PTP_EC_ObjectRemoved in session %u\n", session _id); 2189 LIBMTP_INFO("Received event PTP_EC_ObjectRemoved in session %u\n", session _id);
2214 *event = LIBMTP_EVENT_OBJECT_REMOVED;
2215 *out1 = param1;
2216 break; 2190 break;
2217 case PTP_EC_StoreAdded: 2191 case PTP_EC_StoreAdded:
2218 LIBMTP_INFO("Received event PTP_EC_StoreAdded in session %u\n", session_id ); 2192 LIBMTP_INFO("Received event PTP_EC_StoreAdded in session %u\n", session_id );
2219 /* TODO: rescan storages */ 2193 /* TODO: rescan storages */
2220 *event = LIBMTP_EVENT_STORE_ADDED; 2194 *event = LIBMTP_EVENT_STORE_ADDED;
2221 *out1 = param1; 2195 *out1 = param1;
2222 break; 2196 break;
2223 case PTP_EC_StoreRemoved: 2197 case PTP_EC_StoreRemoved:
2224 LIBMTP_INFO("Received event PTP_EC_StoreRemoved in session %u\n", session_ id); 2198 LIBMTP_INFO("Received event PTP_EC_StoreRemoved in session %u\n", session_ id);
2225 /* TODO: rescan storages */ 2199 /* TODO: rescan storages */
2226 *event = LIBMTP_EVENT_STORE_REMOVED;
2227 *out1 = param1;
2228 break; 2200 break;
2229 case PTP_EC_DevicePropChanged: 2201 case PTP_EC_DevicePropChanged:
2230 LIBMTP_INFO("Received event PTP_EC_DevicePropChanged in session %u\n", ses sion_id); 2202 LIBMTP_INFO("Received event PTP_EC_DevicePropChanged in session %u\n", ses sion_id);
2231 /* TODO: update device properties */ 2203 /* TODO: update device properties */
2232 break; 2204 break;
2233 case PTP_EC_ObjectInfoChanged: 2205 case PTP_EC_ObjectInfoChanged:
2234 LIBMTP_INFO("Received event PTP_EC_ObjectInfoChanged in session %u\n", ses sion_id); 2206 LIBMTP_INFO("Received event PTP_EC_ObjectInfoChanged in session %u\n", ses sion_id);
2235 /* TODO: rescan object cache or just for this one object */ 2207 /* TODO: rescan object cache or just for this one object */
2236 break; 2208 break;
2237 case PTP_EC_DeviceInfoChanged: 2209 case PTP_EC_DeviceInfoChanged:
(...skipping 16 matching lines...) Expand all
2254 case PTP_EC_CaptureComplete : 2226 case PTP_EC_CaptureComplete :
2255 LIBMTP_INFO( "Received event PTP_EC_CaptureComplete in session %u\n", sess ion_id); 2227 LIBMTP_INFO( "Received event PTP_EC_CaptureComplete in session %u\n", sess ion_id);
2256 break; 2228 break;
2257 case PTP_EC_UnreportedStatus : 2229 case PTP_EC_UnreportedStatus :
2258 LIBMTP_INFO( "Received event PTP_EC_UnreportedStatus in session %u\n", ses sion_id); 2230 LIBMTP_INFO( "Received event PTP_EC_UnreportedStatus in session %u\n", ses sion_id);
2259 break; 2231 break;
2260 default : 2232 default :
2261 LIBMTP_INFO( "Received unknown event in session %u\n", session_id); 2233 LIBMTP_INFO( "Received unknown event in session %u\n", session_id);
2262 break; 2234 break;
2263 } 2235 }
2264 }
2265 2236
2266 static void LIBMTP_Read_Event_Cb(PTPParams *params, uint16_t ret_code, 2237 return 0;
2267 PTPContainer *ptp_event, void *user_data) {
2268 event_cb_data_t *data = user_data;
2269 LIBMTP_event_t event = LIBMTP_EVENT_NONE;
2270 uint32_t param1 = 0;
2271 int handler_ret;
2272
2273 switch (ret_code) {
2274 case PTP_RC_OK:
2275 handler_ret = LIBMTP_HANDLER_RETURN_OK;
2276 LIBMTP_Handle_Event(ptp_event, &event, &param1);
2277 break;
2278 case PTP_ERROR_CANCEL:
2279 handler_ret = LIBMTP_HANDLER_RETURN_CANCEL;
2280 break;
2281 default:
2282 handler_ret = LIBMTP_HANDLER_RETURN_ERROR;
2283 break;
2284 }
2285
2286 data->cb(handler_ret, event, param1, data->user_data);
2287 free(data);
2288 } 2238 }
2289 2239
2290 /** 2240 /**
2291 * This function reads events sent by the device, in a non-blocking manner.
2292 * The callback function will be called when an event is received, but for the f unction
2293 * to make progress, polling must take place, using LIBMTP_Handle_Events_Timeout _Completed.
2294 *
2295 * After an event is received, this function should be called again to listen fo r the next
2296 * event.
2297 *
2298 * For now, this non-blocking mechanism only works with libusb-1.0, and not any of the
2299 * other usb library backends. Attempting to call this method with another backe nd will
2300 * always return an error.
2301 *
2302 * @param device a pointer to the MTP device to poll for events.
2303 * @param cb a callback to be invoked when an event is received.
2304 * @param user_data arbitrary user data passed to the callback.
2305 * @return 0 on success, any other value means that the callback was not registe red and
2306 * no event notification will take place.
2307 */
2308 int LIBMTP_Read_Event_Async(LIBMTP_mtpdevice_t *device, LIBMTP_event_cb_fn cb, v oid *user_data) {
2309 PTPParams *params = (PTPParams *) device->params;
2310 event_cb_data_t *data = malloc(sizeof(event_cb_data_t));
2311 uint16_t ret;
2312
2313 data->cb = cb;
2314 data->user_data = user_data;
2315
2316 ret = ptp_usb_event_async(params, LIBMTP_Read_Event_Cb, data);
2317 return ret == PTP_RC_OK ? 0 : -1;
2318 }
2319
2320 /**
2321 * Recursive function that adds MTP devices to a linked list 2241 * Recursive function that adds MTP devices to a linked list
2322 * @param devices a list of raw devices to have real devices created for. 2242 * @param devices a list of raw devices to have real devices created for.
2323 * @return a device pointer to a newly created mtpdevice (used in linked 2243 * @return a device pointer to a newly created mtpdevice (used in linked
2324 * list creation). 2244 * list creation).
2325 */ 2245 */
2326 static LIBMTP_mtpdevice_t * create_usb_mtp_devices(LIBMTP_raw_device_t *devices, int numdevs) 2246 static LIBMTP_mtpdevice_t * create_usb_mtp_devices(LIBMTP_raw_device_t *devices, int numdevs)
2327 { 2247 {
2328 uint8_t i; 2248 uint8_t i;
2329 LIBMTP_mtpdevice_t *mtp_device_list = NULL; 2249 LIBMTP_mtpdevice_t *mtp_device_list = NULL;
2330 LIBMTP_mtpdevice_t *current_device = NULL; 2250 LIBMTP_mtpdevice_t *current_device = NULL;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2381 2301
2382 ret = LIBMTP_Detect_Raw_Devices(&devices, &numdevs); 2302 ret = LIBMTP_Detect_Raw_Devices(&devices, &numdevs);
2383 if (ret != LIBMTP_ERROR_NONE) { 2303 if (ret != LIBMTP_ERROR_NONE) {
2384 *device_list = NULL; 2304 *device_list = NULL;
2385 return ret; 2305 return ret;
2386 } 2306 }
2387 2307
2388 /* Assign linked list of devices */ 2308 /* Assign linked list of devices */
2389 if (devices == NULL || numdevs == 0) { 2309 if (devices == NULL || numdevs == 0) {
2390 *device_list = NULL; 2310 *device_list = NULL;
2391 free(devices);
2392 return LIBMTP_ERROR_NO_DEVICE_ATTACHED; 2311 return LIBMTP_ERROR_NO_DEVICE_ATTACHED;
2393 } 2312 }
2394 2313
2395 *device_list = create_usb_mtp_devices(devices, numdevs); 2314 *device_list = create_usb_mtp_devices(devices, numdevs);
2396 free(devices); 2315 free(devices);
2397 2316
2398 /* TODO: Add wifi device access here */ 2317 /* TODO: Add wifi device access here */
2399 2318
2400 /* We have found some devices but create failed */ 2319 /* We have found some devices but create failed */
2401 if (*device_list == NULL) 2320 if (*device_list == NULL)
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
2489 } 2408 }
2490 } 2409 }
2491 2410
2492 /** 2411 /**
2493 * Adds an error from the PTP layer to the error stack. 2412 * Adds an error from the PTP layer to the error stack.
2494 */ 2413 */
2495 static void add_ptp_error_to_errorstack(LIBMTP_mtpdevice_t *device, 2414 static void add_ptp_error_to_errorstack(LIBMTP_mtpdevice_t *device,
2496 uint16_t ptp_error, 2415 uint16_t ptp_error,
2497 char const * const error_text) 2416 char const * const error_text)
2498 { 2417 {
2499 PTPParams *params = (PTPParams *) device->params;
2500
2501 if (device == NULL) { 2418 if (device == NULL) {
2502 LIBMTP_ERROR("LIBMTP PANIC: Trying to add PTP error to a NULL device!\n"); 2419 LIBMTP_ERROR("LIBMTP PANIC: Trying to add PTP error to a NULL device!\n");
2503 return; 2420 return;
2504 } else { 2421 } else {
2505 char outstr[256]; 2422 char outstr[256];
2506 snprintf(outstr, sizeof(outstr), "PTP Layer error %04x: %s", ptp_error, erro r_text); 2423 snprintf(outstr, sizeof(outstr), "PTP Layer error %04x: %s", ptp_error, erro r_text);
2507 outstr[sizeof(outstr)-1] = '\0'; 2424 outstr[sizeof(outstr)-1] = '\0';
2508 add_error_to_errorstack(device, LIBMTP_ERROR_PTP_LAYER, outstr); 2425 add_error_to_errorstack(device, LIBMTP_ERROR_PTP_LAYER, outstr);
2509 2426
2510 snprintf(outstr, sizeof(outstr), "Error %04x: %s", ptp_error, ptp_strerror(p tp_error, params->deviceinfo.VendorExtensionID)); 2427 snprintf(outstr, sizeof(outstr), "Error %04x: %s", ptp_error, ptp_strerror(p tp_error));
2511 outstr[sizeof(outstr)-1] = '\0'; 2428 outstr[sizeof(outstr)-1] = '\0';
2512 add_error_to_errorstack(device, LIBMTP_ERROR_PTP_LAYER, outstr); 2429 add_error_to_errorstack(device, LIBMTP_ERROR_PTP_LAYER, outstr);
2513 } 2430 }
2514 } 2431 }
2515 2432
2516 /** 2433 /**
2517 * This returns the error stack for a device in case you 2434 * This returns the error stack for a device in case you
2518 * need to either reference the error numbers (e.g. when 2435 * need to either reference the error numbers (e.g. when
2519 * creating multilingual apps with multiple-language text 2436 * creating multilingual apps with multiple-language text
2520 * representations for each error number) or when you need 2437 * representations for each error number) or when you need
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
2656 */ 2573 */
2657 prop = props; 2574 prop = props;
2658 for (i=0;i<nrofprops;i++) { 2575 for (i=0;i<nrofprops;i++) {
2659 if (lasthandle != prop->ObjectHandle) { 2576 if (lasthandle != prop->ObjectHandle) {
2660 cnt++; 2577 cnt++;
2661 lasthandle = prop->ObjectHandle; 2578 lasthandle = prop->ObjectHandle;
2662 } 2579 }
2663 prop++; 2580 prop++;
2664 } 2581 }
2665 lasthandle = 0xffffffff; 2582 lasthandle = 0xffffffff;
2666 params->objects = calloc (cnt, sizeof(PTPObject)); 2583 params->objects = calloc (sizeof(PTPObject),cnt);
2667 prop = props; 2584 prop = props;
2668 i = -1; 2585 i = -1;
2669 for (j=0;j<nrofprops;j++) { 2586 for (j=0;j<nrofprops;j++) {
2670 if (lasthandle != prop->ObjectHandle) { 2587 if (lasthandle != prop->ObjectHandle) {
2671 if (i >= 0) { 2588 if (i >= 0) {
2672 params->objects[i].flags |= PTPOBJECT_OBJECTINFO_LOADED; 2589 params->objects[i].flags |= PTPOBJECT_OBJECTINFO_LOADED;
2673 if (!params->objects[i].oi.Filename) { 2590 if (!params->objects[i].oi.Filename) {
2674 /* I have one such file on my Creative (Marcus) */ 2591 /* I have one such file on my Creative (Marcus) */
2675 params->objects[i].oi.Filename = strdup("<null>"); 2592 params->objects[i].oi.Filename = strdup("<null>");
2676 } 2593 }
(...skipping 29 matching lines...) Expand all
2706 params->objects[i].oi.Filename = strdup(prop->propval.str); 2623 params->objects[i].oi.Filename = strdup(prop->propval.str);
2707 break; 2624 break;
2708 default: { 2625 default: {
2709 MTPProperties *newprops; 2626 MTPProperties *newprops;
2710 2627
2711 /* Copy all of the other MTP oprierties into the per-object proplist */ 2628 /* Copy all of the other MTP oprierties into the per-object proplist */
2712 if (params->objects[i].nrofmtpprops) { 2629 if (params->objects[i].nrofmtpprops) {
2713 newprops = realloc(params->objects[i].mtpprops, 2630 newprops = realloc(params->objects[i].mtpprops,
2714 (params->objects[i].nrofmtpprops+1)*sizeof(MTPProperties)); 2631 (params->objects[i].nrofmtpprops+1)*sizeof(MTPProperties));
2715 } else { 2632 } else {
2716 newprops = calloc(1,sizeof(MTPProperties)); 2633 newprops = calloc(sizeof(MTPProperties),1);
2717 } 2634 }
2718 if (!newprops) return 0; /* FIXME: error handling? */ 2635 if (!newprops) return 0; /* FIXME: error handling? */
2719 params->objects[i].mtpprops = newprops; 2636 params->objects[i].mtpprops = newprops;
2720 memcpy(&params->objects[i].mtpprops[params->objects[i].nrofmtpprops], 2637 memcpy(&params->objects[i].mtpprops[params->objects[i].nrofmtpprops],
2721 &props[j],sizeof(props[j])); 2638 &props[j],sizeof(props[j]));
2722 params->objects[i].nrofmtpprops++; 2639 params->objects[i].nrofmtpprops++;
2723 params->objects[i].flags |= PTPOBJECT_MTPPROPLIST_LOADED; 2640 params->objects[i].flags |= PTPOBJECT_MTPPROPLIST_LOADED;
2724 break; 2641 break;
2725 } 2642 }
2726 } 2643 }
2727 prop++; 2644 prop++;
2728 } 2645 }
2729 /* mark last entry also */ 2646 /* mark last entry also */
2730 params->objects[i].flags |= PTPOBJECT_OBJECTINFO_LOADED; 2647 params->objects[i].flags |= PTPOBJECT_OBJECTINFO_LOADED;
2731 params->nrofobjects = i+1; 2648 params->nrofobjects = i+1;
2732 free (props);
2733 /* The device might not give the list in linear ascending order */ 2649 /* The device might not give the list in linear ascending order */
2734 ptp_objects_sort (params); 2650 ptp_objects_sort (params);
2735 return 0; 2651 return 0;
2736 } 2652 }
2737 2653
2738 /** 2654 /**
2739 * This function will recurse through all the directories on the device, 2655 * This function will recurse through all the directories on the device,
2740 * starting at the root directory, gathering metadata as it moves along. 2656 * starting at the root directory, gathering metadata as it moves along.
2741 * It works better on some devices that will only return data for a 2657 * It works better on some devices that will only return data for a
2742 * certain directory and does not respect the option to get all metadata 2658 * certain directory and does not respect the option to get all metadata
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
3006 return 0; 2922 return 0;
3007 } 2923 }
3008 2924
3009 /** 2925 /**
3010 * This function grabs the first writeable storageid from the 2926 * This function grabs the first writeable storageid from the
3011 * device storage list. 2927 * device storage list.
3012 * @param device a pointer to the MTP device to locate writeable 2928 * @param device a pointer to the MTP device to locate writeable
3013 * storage for. 2929 * storage for.
3014 * @param fitsize a file of this file must fit on the device. 2930 * @param fitsize a file of this file must fit on the device.
3015 */ 2931 */
3016 static uint32_t get_writeable_storageid(LIBMTP_mtpdevice_t *device, 2932 static uint32_t get_writeable_storageid(LIBMTP_mtpdevice_t *device, uint64_t fit size)
3017 » » » » » uint64_t fitsize)
3018 { 2933 {
3019 LIBMTP_devicestorage_t *storage; 2934 LIBMTP_devicestorage_t *storage;
3020 uint32_t store = 0x00000000; //Should this be 0xffffffffu instead? 2935 uint32_t store = 0x00000000; //Should this be 0xffffffffu instead?
3021 int subcall_ret; 2936 int subcall_ret;
3022 2937
3023 // See if there is some storage we can fit this file on. 2938 // See if there is some storage we can fit this file on.
3024 storage = device->storage; 2939 storage = device->storage;
3025 if (storage == NULL) { 2940 if (storage == NULL) {
3026 // Sometimes the storage just cannot be detected. 2941 // Sometimes the storage just cannot be detected.
3027 store = 0x00000000U; 2942 store = 0x00000000U;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3060 "all device storage is full or corrupt."); 2975 "all device storage is full or corrupt.");
3061 return -1; 2976 return -1;
3062 } 2977 }
3063 store = storage->id; 2978 store = storage->id;
3064 } 2979 }
3065 2980
3066 return store; 2981 return store;
3067 } 2982 }
3068 2983
3069 /** 2984 /**
3070 * Tries to suggest a storage_id of a given ID when we have a parent
3071 * @param device a pointer to the device where to search for the storage ID
3072 * @param fitsize a file of this file must fit on the device.
3073 * @param parent_id look for this ID
3074 * @ret storageID
3075 */
3076 static int get_suggested_storage_id(LIBMTP_mtpdevice_t *device,
3077 uint64_t fitsize,
3078 uint32_t parent_id)
3079 {
3080 PTPParams *params = (PTPParams *) device->params;
3081 PTPObject *ob;
3082 uint16_t ret;
3083
3084 ret = ptp_object_want(params, parent_id, PTPOBJECT_MTPPROPLIST_LOADED, &ob);
3085 if ((ret != PTP_RC_OK) || (ob->oi.StorageID == 0)) {
3086 add_ptp_error_to_errorstack(device, ret, "get_suggested_storage_id(): "
3087 "could not get storage id from parent id.");
3088 return get_writeable_storageid(device, fitsize);
3089 } else {
3090 /* OK we know the parent storage, then use that */
3091 return ob->oi.StorageID;
3092 }
3093 }
3094
3095 /**
3096 * This function grabs the freespace from a certain storage in 2985 * This function grabs the freespace from a certain storage in
3097 * device storage list. 2986 * device storage list.
3098 * @param device a pointer to the MTP device to free the storage 2987 * @param device a pointer to the MTP device to free the storage
3099 * list for. 2988 * list for.
3100 * @param storageid the storage ID for the storage to flush and 2989 * @param storageid the storage ID for the storage to flush and
3101 * get free space for. 2990 * get free space for.
3102 * @param freespace the free space on this storage will be returned 2991 * @param freespace the free space on this storage will be returned
3103 * in this variable. 2992 * in this variable.
3104 */ 2993 */
3105 static int get_storage_freespace(LIBMTP_mtpdevice_t *device, 2994 static int get_storage_freespace(LIBMTP_mtpdevice_t *device,
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
3174 printf(" %s: %d.%d\n", 3063 printf(" %s: %d.%d\n",
3175 tmpext->name, 3064 tmpext->name,
3176 tmpext->major, 3065 tmpext->major,
3177 tmpext->minor); 3066 tmpext->minor);
3178 tmpext = tmpext->next; 3067 tmpext = tmpext->next;
3179 } 3068 }
3180 printf("Supported operations:\n"); 3069 printf("Supported operations:\n");
3181 for (i=0;i<params->deviceinfo.OperationsSupported_len;i++) { 3070 for (i=0;i<params->deviceinfo.OperationsSupported_len;i++) {
3182 char txt[256]; 3071 char txt[256];
3183 3072
3184 (void) ptp_render_ofc(params, params->deviceinfo.OperationsSupported[i], 3073 (void) ptp_render_opcode(params, params->deviceinfo.OperationsSupported[i],
3185 sizeof(txt), txt); 3074 sizeof(txt), txt);
3186 printf(" %04x: %s\n", params->deviceinfo.OperationsSupported[i], txt); 3075 printf(" %04x: %s\n", params->deviceinfo.OperationsSupported[i], txt);
3187 } 3076 }
3188 printf("Events supported:\n"); 3077 printf("Events supported:\n");
3189 if (params->deviceinfo.EventsSupported_len == 0) { 3078 if (params->deviceinfo.EventsSupported_len == 0) {
3190 printf(" None.\n"); 3079 printf(" None.\n");
3191 } else { 3080 } else {
3192 for (i=0;i<params->deviceinfo.EventsSupported_len;i++) { 3081 for (i=0;i<params->deviceinfo.EventsSupported_len;i++) {
3193 printf(" 0x%04x\n", params->deviceinfo.EventsSupported[i]); 3082 printf(" 0x%04x\n", params->deviceinfo.EventsSupported[i]);
3194 } 3083 }
(...skipping 824 matching lines...) Expand 10 before | Expand all | Expand 10 after
4019 localtypelen++; 3908 localtypelen++;
4020 } 3909 }
4021 3910
4022 *filetypes = localtypes; 3911 *filetypes = localtypes;
4023 *length = localtypelen; 3912 *length = localtypelen;
4024 3913
4025 return 0; 3914 return 0;
4026 } 3915 }
4027 3916
4028 /** 3917 /**
4029 * This function checks if the device has some specific capabilities, in
4030 * order to avoid calling APIs that may disturb the device.
4031 *
4032 * @param device a pointer to the device to check the capability on.
4033 * @param cap the capability to check.
4034 * @return 0 if not supported, any other value means the device has the
4035 * requested capability.
4036 */
4037 int LIBMTP_Check_Capability(LIBMTP_mtpdevice_t *device, LIBMTP_devicecap_t cap)
4038 {
4039 switch (cap) {
4040 case LIBMTP_DEVICECAP_GetPartialObject:
4041 return (ptp_operation_issupported(device->params,
4042 PTP_OC_GetPartialObject) ||
4043 ptp_operation_issupported(device->params,
4044 PTP_OC_ANDROID_GetPartialObject64));
4045 case LIBMTP_DEVICECAP_SendPartialObject:
4046 return ptp_operation_issupported(device->params,
4047 PTP_OC_ANDROID_SendPartialObject);
4048 case LIBMTP_DEVICECAP_EditObjects:
4049 return (ptp_operation_issupported(device->params,
4050 PTP_OC_ANDROID_TruncateObject) &&
4051 ptp_operation_issupported(device->params,
4052 PTP_OC_ANDROID_BeginEditObject) &&
4053 ptp_operation_issupported(device->params,
4054 PTP_OC_ANDROID_EndEditObject));
4055 /*
4056 * Handle other capabilities here, this is also a good place to
4057 * blacklist some advanced operations on specific devices if need
4058 * be.
4059 */
4060
4061 default:
4062 break;
4063 }
4064 return 0;
4065 }
4066
4067 /**
4068 * This function updates all the storage id's of a device and their 3918 * This function updates all the storage id's of a device and their
4069 * properties, then creates a linked list and puts the list head into 3919 * properties, then creates a linked list and puts the list head into
4070 * the device struct. It also optionally sorts this list. If you want 3920 * the device struct. It also optionally sorts this list. If you want
4071 * to display storage information in your application you should call 3921 * to display storage information in your application you should call
4072 * this function, then dereference the device struct 3922 * this function, then dereference the device struct
4073 * (<code>device-&gt;storage</code>) to get out information on the storage. 3923 * (<code>device-&gt;storage</code>) to get out information on the storage.
4074 * 3924 *
4075 * You need to call this everytime you want to update the 3925 * You need to call this everytime you want to update the
4076 * <code>device-&gt;storage</code> list, for example anytime you need 3926 * <code>device-&gt;storage</code> list, for example anytime you need
4077 * to check available storage somewhere. 3927 * to check available storage somewhere.
(...skipping 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after
5267 return PTP_ERROR_CANCEL; 5117 return PTP_ERROR_CANCEL;
5268 default: 5118 default:
5269 return PTP_ERROR_IO; 5119 return PTP_ERROR_IO;
5270 } 5120 }
5271 } 5121 }
5272 5122
5273 /** 5123 /**
5274 * This is a manual conversion from MTPDataPutFunc to PTPDataPutFunc 5124 * This is a manual conversion from MTPDataPutFunc to PTPDataPutFunc
5275 * to isolate the internal type. 5125 * to isolate the internal type.
5276 */ 5126 */
5277 static uint16_t put_func_wrapper(PTPParams* params, void* priv, unsigned long se ndlen, unsigned char *data) 5127 static uint16_t put_func_wrapper(PTPParams* params, void* priv, unsigned long se ndlen, unsigned char *data, unsigned long *putlen)
5278 { 5128 {
5279 MTPDataHandler *handler = (MTPDataHandler *)priv; 5129 MTPDataHandler *handler = (MTPDataHandler *)priv;
5280 uint16_t ret; 5130 uint16_t ret;
5281 uint32_t local_putlen = 0; 5131 uint32_t local_putlen = 0;
5282
5283 ret = handler->putfunc(params, handler->priv, sendlen, data, &local_putlen); 5132 ret = handler->putfunc(params, handler->priv, sendlen, data, &local_putlen);
5284 5133 *putlen = local_putlen;
5285 switch (ret) 5134 switch (ret)
5286 { 5135 {
5287 case LIBMTP_HANDLER_RETURN_OK: 5136 case LIBMTP_HANDLER_RETURN_OK:
5288 if (local_putlen != sendlen)
5289 return PTP_ERROR_IO;
5290 return PTP_RC_OK; 5137 return PTP_RC_OK;
5291 case LIBMTP_HANDLER_RETURN_ERROR: 5138 case LIBMTP_HANDLER_RETURN_ERROR:
5292 return PTP_ERROR_IO; 5139 return PTP_ERROR_IO;
5293 case LIBMTP_HANDLER_RETURN_CANCEL: 5140 case LIBMTP_HANDLER_RETURN_CANCEL:
5294 return PTP_ERROR_CANCEL; 5141 return PTP_ERROR_CANCEL;
5295 default: 5142 default:
5296 return PTP_ERROR_IO; 5143 return PTP_ERROR_IO;
5297 } 5144 }
5298 } 5145 }
5299 5146
(...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after
6235 #if 0 6082 #if 0
6236 // Sanity check: no zerolength files on some devices? 6083 // Sanity check: no zerolength files on some devices?
6237 // If the zerolength files cause problems on some devices, 6084 // If the zerolength files cause problems on some devices,
6238 // then add a bug flag for this. 6085 // then add a bug flag for this.
6239 if (filedata->filesize == 0) { 6086 if (filedata->filesize == 0) {
6240 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "send_file_object_info (): " 6087 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "send_file_object_info (): "
6241 "File of zero size."); 6088 "File of zero size.");
6242 return -1; 6089 return -1;
6243 } 6090 }
6244 #endif 6091 #endif
6092
6245 if (filedata->storage_id != 0) { 6093 if (filedata->storage_id != 0) {
6246 store = filedata->storage_id; 6094 store = filedata->storage_id;
6247 } else { 6095 } else {
6248 store = get_suggested_storage_id(device, filedata->filesize, localph); 6096 store = get_writeable_storageid(device, filedata->filesize);
6249 } 6097 }
6250
6251 // Detect if something non-primary is in use. 6098 // Detect if something non-primary is in use.
6252 storage = device->storage; 6099 storage = device->storage;
6253 if (storage != NULL && store != storage->id) { 6100 if (storage != NULL && store != storage->id) {
6254 use_primary_storage = 0; 6101 use_primary_storage = 0;
6255 } 6102 }
6256 6103
6257 /* 6104 /*
6258 * If no destination folder was given, look up a default 6105 * If no destination folder was given, look up a default
6259 * folder if possible. Perhaps there is some way of retrieveing 6106 * folder if possible. Perhaps there is some way of retrieveing
6260 * the default folder for different forms of content, what 6107 * the default folder for different forms of content, what
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
6455 } 6302 }
6456 } else if (ptp_operation_issupported(params,PTP_OC_SendObjectInfo)) { 6303 } else if (ptp_operation_issupported(params,PTP_OC_SendObjectInfo)) {
6457 PTPObjectInfo new_file; 6304 PTPObjectInfo new_file;
6458 6305
6459 memset(&new_file, 0, sizeof(PTPObjectInfo)); 6306 memset(&new_file, 0, sizeof(PTPObjectInfo));
6460 6307
6461 new_file.Filename = filedata->filename; 6308 new_file.Filename = filedata->filename;
6462 if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) { 6309 if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
6463 strip_7bit_from_utf8(new_file.Filename); 6310 strip_7bit_from_utf8(new_file.Filename);
6464 } 6311 }
6465 if (filedata->filesize > 0xFFFFFFFFL) { 6312 // We lose precision here.
6466 // This is a kludge in the MTP standard for large files. 6313 new_file.ObjectCompressedSize = (uint32_t) filedata->filesize;
6467 new_file.ObjectCompressedSize = (uint32_t) 0xFFFFFFFF;
6468 } else {
6469 new_file.ObjectCompressedSize = (uint32_t) filedata->filesize;
6470 }
6471 new_file.ObjectFormat = of; 6314 new_file.ObjectFormat = of;
6472 new_file.StorageID = store; 6315 new_file.StorageID = store;
6473 new_file.ParentObject = localph; 6316 new_file.ParentObject = localph;
6474 new_file.ModificationDate = time(NULL); 6317 new_file.ModificationDate = time(NULL);
6475 6318
6476 // Create the object 6319 // Create the object
6477 ret = ptp_sendobjectinfo(params, &store, &localph, &filedata->item_id, &new_ file); 6320 ret = ptp_sendobjectinfo(params, &store, &localph, &filedata->item_id, &new_ file);
6478 6321
6479 if (ret != PTP_RC_OK) { 6322 if (ret != PTP_RC_OK) {
6480 add_ptp_error_to_errorstack(device, ret, "send_file_object_info(): " 6323 add_ptp_error_to_errorstack(device, ret, "send_file_object_info(): "
(...skipping 983 matching lines...) Expand 10 before | Expand all | Expand 10 after
7464 * for a folder is "association". The PTP/MTP devices does not 7307 * for a folder is "association". The PTP/MTP devices does not
7465 * have an internal "folder" concept really, it contains a flat 7308 * have an internal "folder" concept really, it contains a flat
7466 * list of all files and some file are "associations" that other 7309 * list of all files and some file are "associations" that other
7467 * files and folders may refer to as its "parent". 7310 * files and folders may refer to as its "parent".
7468 * 7311 *
7469 * @param device a pointer to the device to create the folder on. 7312 * @param device a pointer to the device to create the folder on.
7470 * @param name the name of the new folder. Note this can be modified 7313 * @param name the name of the new folder. Note this can be modified
7471 * if the device does not support all the characters in the 7314 * if the device does not support all the characters in the
7472 * name. 7315 * name.
7473 * @param parent_id id of parent folder to add the new folder to, 7316 * @param parent_id id of parent folder to add the new folder to,
7474 * or 0xFFFFFFFF to put it in the root directory. 7317 * or 0 to put it in the root directory.
7475 * @param storage_id id of the storage to add this new folder to. 7318 * @param storage_id id of the storage to add this new folder to.
7476 * notice that you cannot mismatch storage id and parent id: 7319 * notice that you cannot mismatch storage id and parent id:
7477 * they must both be on the same storage! Pass in 0 if you 7320 * they must both be on the same storage! Pass in 0 if you
7478 * want to create this folder on the default storage. 7321 * want to create this folder on the default storage.
7479 * @return id to new folder or 0 if an error occured 7322 * @return id to new folder or 0 if an error occured
7480 */ 7323 */
7481 uint32_t LIBMTP_Create_Folder(LIBMTP_mtpdevice_t *device, char *name, 7324 uint32_t LIBMTP_Create_Folder(LIBMTP_mtpdevice_t *device, char *name,
7482 uint32_t parent_id, uint32_t storage_id) 7325 uint32_t parent_id, uint32_t storage_id)
7483 { 7326 {
7484 PTPParams *params = (PTPParams *) device->params; 7327 PTPParams *params = (PTPParams *) device->params;
7485 PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo; 7328 PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
7486 uint32_t parenthandle = 0; 7329 uint32_t parenthandle = 0;
7487 uint32_t store; 7330 uint32_t store;
7488 PTPObjectInfo new_folder; 7331 PTPObjectInfo new_folder;
7489 uint16_t ret; 7332 uint16_t ret;
7490 uint32_t new_id = 0; 7333 uint32_t new_id = 0;
7491 7334
7492 if (storage_id == 0) { 7335 if (storage_id == 0) {
7493 // I'm just guessing that a folder may require 512 bytes 7336 // I'm just guessing that a folder may require 512 bytes
7494 store = get_suggested_storage_id(device, 512, parent_id); 7337 store = get_writeable_storageid(device, 512);
7495 } else { 7338 } else {
7496 store = storage_id; 7339 store = storage_id;
7497 } 7340 }
7498 parenthandle = parent_id; 7341 parenthandle = parent_id;
7499 7342
7500 memset(&new_folder, 0, sizeof(new_folder)); 7343 memset(&new_folder, 0, sizeof(new_folder));
7501 new_folder.Filename = name; 7344 new_folder.Filename = name;
7502 if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) { 7345 if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
7503 strip_7bit_from_utf8(new_folder.Filename); 7346 strip_7bit_from_utf8(new_folder.Filename);
7504 } 7347 }
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
7791 //uint8_t data[2]; 7634 //uint8_t data[2];
7792 7635
7793 // NULL check 7636 // NULL check
7794 if (!name) { 7637 if (!name) {
7795 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_l ist(): list name was NULL, using default name \"Unknown\""); 7638 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_l ist(): list name was NULL, using default name \"Unknown\"");
7796 return -1; 7639 return -1;
7797 } 7640 }
7798 7641
7799 if (storageid == 0) { 7642 if (storageid == 0) {
7800 // I'm just guessing that an abstract list may require 512 bytes 7643 // I'm just guessing that an abstract list may require 512 bytes
7801 store = get_suggested_storage_id(device, 512, localph); 7644 store = get_writeable_storageid(device, 512);
7802 } else { 7645 } else {
7803 store = storageid; 7646 store = storageid;
7804 } 7647 }
7805 7648
7806 // Check if we can create an object of this type 7649 // Check if we can create an object of this type
7807 for ( i=0; i < params->deviceinfo.ImageFormats_len; i++ ) { 7650 for ( i=0; i < params->deviceinfo.ImageFormats_len; i++ ) {
7808 if (params->deviceinfo.ImageFormats[i] == objectformat) { 7651 if (params->deviceinfo.ImageFormats[i] == objectformat) {
7809 supported = 1; 7652 supported = 1;
7810 break; 7653 break;
7811 } 7654 }
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
8233 "could not set album artist name."); 8076 "could not set album artist name.");
8234 } 8077 }
8235 break; 8078 break;
8236 case PTP_OPC_Artist: 8079 case PTP_OPC_Artist:
8237 // Update artist 8080 // Update artist
8238 ret = set_object_string(device, objecthandle, PTP_OPC_Artist, artist); 8081 ret = set_object_string(device, objecthandle, PTP_OPC_Artist, artist);
8239 if (ret != 0) { 8082 if (ret != 0) {
8240 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract _list(): " 8083 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract _list(): "
8241 "could not set artist name."); 8084 "could not set artist name.");
8242 } 8085 }
8243 break;
8244 case PTP_OPC_Composer: 8086 case PTP_OPC_Composer:
8245 // Update composer 8087 // Update composer
8246 ret = set_object_string(device, objecthandle, PTP_OPC_Composer, composer ); 8088 ret = set_object_string(device, objecthandle, PTP_OPC_Composer, composer );
8247 if (ret != 0) { 8089 if (ret != 0) {
8248 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract _list(): " 8090 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract _list(): "
8249 "could not set composer name."); 8091 "could not set composer name.");
8250 } 8092 }
8251 break; 8093 break;
8252 case PTP_OPC_Genre: 8094 case PTP_OPC_Genre:
8253 // Update genre (but only if valid) 8095 // Update genre (but only if valid)
8254 if(genre) { 8096 if(genre) {
8255 ret = set_object_string(device, objecthandle, PTP_OPC_Genre, genre); 8097 ret = set_object_string(device, objecthandle, PTP_OPC_Genre, genre);
8256 if (ret != 0) { 8098 if (ret != 0) {
8257 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstra ct_list(): " 8099 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstra ct_list(): "
8258 "could not set genre."); 8100 "could not set genre.");
8259 } 8101 }
8260 } 8102 }
8261 break; 8103 break;
8262 case PTP_OPC_DateModified: 8104 case PTP_OPC_DateModified:
8263 // Update date modified 8105 // Update date modified
8264 if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) { 8106 if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
8265 char *tmpdate = get_iso8601_stamp(); 8107 char *tmpdate = get_iso8601_stamp();
8266 ret = set_object_string(device, objecthandle, PTP_OPC_DateModified, tm pdate); 8108 ret = set_object_string(device, objecthandle, PTP_OPC_DateModified, tm pdate);
8267 if (ret != 0) { 8109 if (ret != 0) {
8268 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstra ct_list(): " 8110 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstra ct_list(): "
8269 "could not set modification date."); 8111 "could not set modification date.");
8270 } 8112 }
8271 free(tmpdate); 8113 free(tmpdate);
8272 } 8114 }
8273 break;
8274 default: 8115 default:
8275 break; 8116 break;
8276 } 8117 }
8277 } 8118 }
8278 } else { 8119 } else {
8279 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list( ): " 8120 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list( ): "
8280 "Your device doesn't seem to support any known way o f setting metadata."); 8121 "Your device doesn't seem to support any known way o f setting metadata.");
8281 free(properties); 8122 free(properties);
8282 return -1; 8123 return -1;
8283 } 8124 }
(...skipping 829 matching lines...) Expand 10 before | Expand all | Expand 10 after
9113 { 8954 {
9114 PTPParams *params = (PTPParams *) device->params; 8955 PTPParams *params = (PTPParams *) device->params;
9115 uint16_t ret; 8956 uint16_t ret;
9116 8957
9117 ret = ptp_getthumb(params, id, data, size); 8958 ret = ptp_getthumb(params, id, data, size);
9118 if (ret == PTP_RC_OK) 8959 if (ret == PTP_RC_OK)
9119 return 0; 8960 return 0;
9120 return -1; 8961 return -1;
9121 } 8962 }
9122 8963
9123
9124 int LIBMTP_GetPartialObject(LIBMTP_mtpdevice_t *device, uint32_t const id,
9125 uint64_t offset, uint32_t maxbytes,
9126 unsigned char **data, unsigned int *size)
9127 {
9128 PTPParams *params = (PTPParams *) device->params;
9129 uint16_t ret;
9130
9131 if (!ptp_operation_issupported(params, PTP_OC_ANDROID_GetPartialObject64)) {
9132 if (!ptp_operation_issupported(params, PTP_OC_GetPartialObject)) {
9133 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
9134 "LIBMTP_GetPartialObject: PTP_OC_GetPartialObject not supported");
9135 return -1;
9136 }
9137
9138 if (offset >> 32 != 0) {
9139 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
9140 "LIBMTP_GetPartialObject: PTP_OC_GetPartialObject only supports 32bit of fsets");
9141 return -1;
9142 }
9143
9144 ret = ptp_getpartialobject(params, id, (uint32_t)offset, maxbytes, data, siz e);
9145 } else {
9146 ret = ptp_android_getpartialobject64(params, id, offset, maxbytes, data, siz e);
9147 }
9148 if (ret == PTP_RC_OK)
9149 return 0;
9150 return -1;
9151 }
9152
9153
9154 int LIBMTP_SendPartialObject(LIBMTP_mtpdevice_t *device, uint32_t const id,
9155 uint64_t offset, unsigned char *data, unsigned int size)
9156 {
9157 PTPParams *params = (PTPParams *) device->params;
9158 uint16_t ret;
9159
9160 if (!ptp_operation_issupported(params, PTP_OC_ANDROID_SendPartialObject)) {
9161 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
9162 "LIBMTP_SendPartialObject: PTP_OC_ANDROID_SendPartialObject not supported" );
9163 return -1;
9164 }
9165
9166 ret = ptp_android_sendpartialobject(params, id, offset, data, size);
9167 if (ret == PTP_RC_OK)
9168 return 0;
9169 return -1;
9170 }
9171
9172
9173 int LIBMTP_BeginEditObject(LIBMTP_mtpdevice_t *device, uint32_t const id)
9174 {
9175 PTPParams *params = (PTPParams *) device->params;
9176 uint16_t ret;
9177
9178 if (!ptp_operation_issupported(params, PTP_OC_ANDROID_BeginEditObject)) {
9179 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
9180 "LIBMTP_BeginEditObject: PTP_OC_ANDROID_BeginEditObject not supported");
9181 return -1;
9182 }
9183
9184 ret = ptp_android_begineditobject(params, id);
9185 if (ret == PTP_RC_OK)
9186 return 0;
9187 return -1;
9188 }
9189
9190
9191 int LIBMTP_EndEditObject(LIBMTP_mtpdevice_t *device, uint32_t const id)
9192 {
9193 PTPParams *params = (PTPParams *) device->params;
9194 uint16_t ret;
9195
9196 if (!ptp_operation_issupported(params, PTP_OC_ANDROID_EndEditObject)) {
9197 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
9198 "LIBMTP_EndEditObject: PTP_OC_ANDROID_EndEditObject not supported");
9199 return -1;
9200 }
9201
9202 ret = ptp_android_endeditobject(params, id);
9203 if (ret == PTP_RC_OK) {
9204 // update cached object properties if metadata cache exists
9205 update_metadata_cache(device, id);
9206 return 0;
9207 }
9208 return -1;
9209 }
9210
9211
9212 int LIBMTP_TruncateObject(LIBMTP_mtpdevice_t *device, uint32_t const id,
9213 uint64_t offset)
9214 {
9215 PTPParams *params = (PTPParams *) device->params;
9216 uint16_t ret;
9217
9218 if (!ptp_operation_issupported(params, PTP_OC_ANDROID_TruncateObject)) {
9219 add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
9220 "LIBMTP_TruncateObject: PTP_OC_ANDROID_TruncateObject not supported");
9221 return -1;
9222 }
9223
9224 ret = ptp_android_truncate(params, id, offset);
9225 if (ret == PTP_RC_OK)
9226 return 0;
9227 return -1;
9228 }
9229
9230
9231 /** 8964 /**
9232 * Get thumbnail format of a file. 8965 * Get thumbnail format of a file.
9233 * @param device a pointer to the device to get thumbnail format of. 8966 * @param device a pointer to the device to get thumbnail format of.
9234 * @param id the object ID of the file to get thumbnail format of. 8967 * @param id the object ID of the file to get thumbnail format of.
9235 * @return 0 on success, any other value means failure. 8968 * @return 0 on success, any other value means failure.
9236 */ 8969 */
9237 int LIBMTP_Get_Thumbnail_Format(LIBMTP_mtpdevice_t *device, uint32_t const id, 8970 int LIBMTP_Get_Thumbnail_Format(LIBMTP_mtpdevice_t *device, uint32_t const id,
9238 uint16_t *format) 8971 uint16_t *format)
9239 { 8972 {
9240 PTPParams *params = (PTPParams *) device->params; 8973 PTPParams *params = (PTPParams *) device->params;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
9307 * @param device the device which may have a cache to which the object should be updated. 9040 * @param device the device which may have a cache to which the object should be updated.
9308 * @param object_id the object to update. 9041 * @param object_id the object to update.
9309 */ 9042 */
9310 static void update_metadata_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id ) 9043 static void update_metadata_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id )
9311 { 9044 {
9312 PTPParams *params = (PTPParams *)device->params; 9045 PTPParams *params = (PTPParams *)device->params;
9313 9046
9314 ptp_remove_object_from_cache(params, object_id); 9047 ptp_remove_object_from_cache(params, object_id);
9315 add_object_to_cache(device, object_id); 9048 add_object_to_cache(device, object_id);
9316 } 9049 }
OLDNEW
« no previous file with comments | « src/libmtp.h ('k') | src/libmtp.sym » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698