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