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