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

Side by Side Diff: src/libmtp.c

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