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