Some storage havin' fun, mark Cowon D2 broken for all list
diff --git a/ChangeLog b/ChangeLog
index e937888..43174ba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2007-09-04 Linus Walleij <[email protected]>
+
+ * src/libmtp.c: make sure we query recursively supplying each
+ storage ID in turn, so we spin over storages. Also check
+ what storage may be available to store a file, if the first
+ one fails, try the next!
+
2007-09-01 Linus Walleij <[email protected]>
* src/ptp-pack.c: make the resulting MTP proplist sorted by
diff --git a/src/libmtp.c b/src/libmtp.c
index 5f6054b..a7d6cc5 100644
--- a/src/libmtp.c
+++ b/src/libmtp.c
@@ -81,12 +81,20 @@
uint16_t ptp_error,
char const * const error_text);
static void flush_handles(LIBMTP_mtpdevice_t *device);
-static void get_handles_recursively(LIBMTP_mtpdevice_t *device, PTPParams *params, PTPObjectHandles *handles, uint32_t parent);
+static void get_handles_recursively(LIBMTP_mtpdevice_t *device,
+ PTPParams *params,
+ PTPObjectHandles *handles,
+ uint32_t storageid,
+ uint32_t parent);
static void free_storage_list(LIBMTP_mtpdevice_t *device);
static int sort_storage_by(LIBMTP_mtpdevice_t *device, int const sortby);
static uint32_t get_first_storageid(LIBMTP_mtpdevice_t *device);
-static int get_first_storage_freespace(LIBMTP_mtpdevice_t *device,uint64_t *freespace);
-static int check_if_file_fits(LIBMTP_mtpdevice_t *device, uint64_t const filesize);
+static int get_storage_freespace(LIBMTP_mtpdevice_t *device,
+ LIBMTP_devicestorage_t *storage,
+ uint64_t *freespace);
+static int check_if_file_fits(LIBMTP_mtpdevice_t *device,
+ LIBMTP_devicestorage_t *storage,
+ uint64_t const filesize);
static uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype);
static LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype);
static int get_device_unicode_property(LIBMTP_mtpdevice_t *device,
@@ -962,20 +970,21 @@
mtp_device->default_album_folder = 0;
mtp_device->default_text_folder = 0;
- /*
- * Then get the handles and try to locate the default folders.
- * This has the desired side effect of caching all handles from
- * the device which speeds up later operations.
- */
- flush_handles(mtp_device);
-
/* Set initial storage information */
mtp_device->storage = NULL;
if (LIBMTP_Get_Storage(mtp_device, LIBMTP_STORAGE_SORTBY_NOTSORTED) == -1) {
add_error_to_errorstack(mtp_device,
LIBMTP_ERROR_GENERAL,
"Get Storage information failed.");
+ mtp_device->storage = NULL;
}
+
+ /*
+ * Then get the handles and try to locate the default folders.
+ * This has the desired side effect of caching all handles from
+ * the device which speeds up later operations.
+ */
+ flush_handles(mtp_device);
/* Add the device to the list */
mtp_device->next = NULL;
@@ -1210,7 +1219,8 @@
* problems getting the metadata.
* @return 0 if all was OK, -1 on failure.
*/
-static int get_all_metadata_fast(LIBMTP_mtpdevice_t *device)
+static int get_all_metadata_fast(LIBMTP_mtpdevice_t *device,
+ uint32_t storage)
{
PTPParams *params = (PTPParams *) device->params;
int cnt = 0;
@@ -1259,13 +1269,10 @@
prop = proplist;
i = -1;
while (prop) {
- // Actually, this assumes all properties for a certain object
- // will come after each other, which is not strictly required.
- // The list should be cached, then sorted, then stored.
if (lasthandle != prop->ObjectHandle) {
if (i >= 0) {
if (!params->objectinfo[i].Filename) {
- /* I have one such file on my Creative */
+ /* I have one such file on my Creative (Marcus) */
params->objectinfo[i].Filename = strdup("<null>");
}
}
@@ -1314,14 +1321,18 @@
* certain directory and does not respect the option to get all metadata
* for all objects.
*/
-static void get_handles_recursively(LIBMTP_mtpdevice_t *device, PTPParams *params, PTPObjectHandles *handles, uint32_t parent)
+static void get_handles_recursively(LIBMTP_mtpdevice_t *device,
+ PTPParams *params,
+ PTPObjectHandles *handles,
+ uint32_t storageid,
+ uint32_t parent)
{
PTPObjectHandles currentHandles;
int i = 0;
uint32_t old_handles;
uint16_t ret = ptp_getobjecthandles(params,
- PTP_GOH_ALL_STORAGE,
+ storageid,
PTP_GOH_ALL_FORMATS,
parent,
¤tHandles);
@@ -1359,7 +1370,7 @@
oi = ¶ms->objectinfo[old_handles + i];
if (oi->ObjectFormat == PTP_OFC_Association) {
- get_handles_recursively(device, params, handles, currentHandles.Handler[i]);
+ get_handles_recursively(device, params, handles, storageid, currentHandles.Handler[i]);
}
} else {
add_error_to_errorstack(device,
@@ -1406,15 +1417,28 @@
&& !(ptp_usb->device_flags & DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST)
&& !(ptp_usb->device_flags & DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL)) {
// Use the fast method. Ignore return value for now.
- ret = get_all_metadata_fast(device);
+ ret = get_all_metadata_fast(device, PTP_GOH_ALL_STORAGE);
}
// If the previous failed or returned no objects, use classic
// methods instead.
if (params->proplist == NULL) {
// Get all the handles using just standard commands.
- get_handles_recursively(device, params,
- ¶ms->handles,
- PTP_GOH_ROOT_PARENT);
+ if (device->storage == NULL) {
+ get_handles_recursively(device, params,
+ ¶ms->handles,
+ PTP_GOH_ALL_STORAGE,
+ PTP_GOH_ROOT_PARENT);
+ } else {
+ // Get handles for each storage in turn.
+ LIBMTP_devicestorage_t *storage = device->storage;
+ while(storage != NULL) {
+ get_handles_recursively(device, params,
+ ¶ms->handles,
+ storage->id,
+ PTP_GOH_ROOT_PARENT);
+ storage = storage->next;
+ }
+ }
}
for(i = 0; i < params->handles.n; i++) {
@@ -1591,21 +1615,23 @@
}
/**
- * This function grabs the freespace from the first storage in
+ * This function grabs the freespace from a certain storage in
* device storage list.
* @param device a pointer to the MTP device to free the storage
* list for.
+ * @param storageid the storage ID for the storage to flush and
+ * get free space for.
+ * @param freespace the free space on this storage will be returned
+ * in this variable.
*/
-static int get_first_storage_freespace(LIBMTP_mtpdevice_t *device, uint64_t *freespace)
+static int get_storage_freespace(LIBMTP_mtpdevice_t *device,
+ LIBMTP_devicestorage_t *storage,
+ uint64_t *freespace)
{
- LIBMTP_devicestorage_t *storage = device->storage;
PTPParams *params = (PTPParams *) device->params;
- if(storage == NULL) {
- return -1;
- }
// Always query the device about this, since some models explicitly
- // needs that.
+ // needs that. We flush all data on queries storage here.
if (ptp_operation_issupported(params,PTP_OC_GetStorageInfo)) {
PTPStorageInfo storageInfo;
uint16_t ret;
@@ -2135,9 +2161,12 @@
* if it's too big.
* @param device a pointer to the device.
* @param filesize the size of the file to check whether it will fit.
+ * @param storageid the ID of the storage to try to fit the file on.
* @return 0 if the file fits, any other value means failure.
*/
-static int check_if_file_fits(LIBMTP_mtpdevice_t *device, uint64_t const filesize) {
+static int check_if_file_fits(LIBMTP_mtpdevice_t *device,
+ LIBMTP_devicestorage_t *storage,
+ uint64_t const filesize) {
PTPParams *params = (PTPParams *) device->params;
uint64_t freebytes;
int ret;
@@ -2147,13 +2176,13 @@
return 0;
}
- ret = get_first_storage_freespace(device,&freebytes);
+ ret = get_storage_freespace(device, storage, &freebytes);
if (ret != 0) {
- add_ptp_error_to_errorstack(device, ret, "check_if_file_fits(): error checking free storage.");
+ add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
+ "check_if_file_fits(): error checking free storage.");
return -1;
} else {
if (filesize > freebytes) {
- add_error_to_errorstack(device, LIBMTP_ERROR_STORAGE_FULL, "check_if_file_fits(): device storage is full.");
return -1;
}
}
@@ -3778,7 +3807,8 @@
void const * const data, uint32_t const parenthandle)
{
uint16_t ret;
- uint32_t store = get_first_storageid(device);
+ LIBMTP_devicestorage_t *storage;
+ uint32_t store;
uint32_t localph = parenthandle;
PTPParams *params = (PTPParams *) device->params;
PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
@@ -3787,18 +3817,28 @@
uint16_t of = map_libmtp_type_to_ptp_type(filedata->filetype);
uint8_t nonconsumable = 0x01U; /* By default it is non-consumable */
- subcall_ret = check_if_file_fits(device, filedata->filesize);
- if (subcall_ret != 0) {
- return -1;
- }
-
- // Sanity check: no zerolength files
+ // Sanity check: no zerolength files.
if (filedata->filesize == 0) {
add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Send_File_From_File_Descriptor(): "
"File of zero size.");
return -1;
}
+ // See if there is some storage we can fit this file on.
+ storage = device->storage;
+ while(storage != NULL) {
+ subcall_ret = check_if_file_fits(device, storage, filedata->filesize);
+ if (subcall_ret != 0) {
+ storage = storage->next;
+ }
+ break;
+ }
+ if (storage == NULL) {
+ add_error_to_errorstack(device, LIBMTP_ERROR_STORAGE_FULL, "LIBMTP_Send_File_From_File_Descriptor(): "
+ "all device storage is full or corrupt.");
+ return -1;
+ }
+ store = storage->id;
/*
* If this file is among the supported filetypes for this device,
diff --git a/src/libusb-glue.c b/src/libusb-glue.c
index dca96da..be630cd 100644
--- a/src/libusb-glue.c
+++ b/src/libusb-glue.c
@@ -404,7 +404,8 @@
// Reported by Roberth Karman
{"Cowon iAudio 7 (MTP mode)", 0x0e21, 0x0751, DEVICE_FLAG_NONE },
// Reported by TJ Something <[email protected]>
- {"Cowon iAudio D2 (MTP mode)", 0x0e21, 0x0801, DEVICE_FLAG_UNLOAD_DRIVER },
+ {"Cowon iAudio D2 (MTP mode)", 0x0e21, 0x0801,
+ DEVICE_FLAG_UNLOAD_DRIVER | DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL },
/*
* Insignia, dual-mode.