| 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 |