Index: src/libusb1-glue.c |
diff --git a/src/libusb1-glue.c b/src/libusb1-glue.c |
index 2ae89c415db89e656947fed19f21c6b3fc48c4d7..187c485fd1ded2dcabdda042db56c03284c6c76a 100644 |
--- a/src/libusb1-glue.c |
+++ b/src/libusb1-glue.c |
@@ -77,11 +77,18 @@ struct mtpdevice_list_struct { |
}; |
typedef struct mtpdevice_list_struct mtpdevice_list_t; |
+struct ptp_event_cb_data { |
+ PTPEventCbFn cb; |
+ void *user_data; |
+ PTPParams *params; |
+}; |
+ |
static const LIBMTP_device_entry_t mtp_device_table[] = { |
/* We include an .h file which is shared between us and libgphoto2 */ |
#include "music-players.h" |
}; |
-static const int mtp_device_table_size = sizeof(mtp_device_table) / sizeof(LIBMTP_device_entry_t); |
+static const int mtp_device_table_size = |
+ sizeof(mtp_device_table) / sizeof(LIBMTP_device_entry_t); |
// Local functions |
static LIBMTP_error_number_t init_usb(); |
@@ -96,10 +103,14 @@ static int find_interface_and_endpoints(libusb_device *dev, |
int* outep_maxpacket, |
int* intep); |
static void clear_stall(PTP_USB* ptp_usb); |
-static int init_ptp_usb (PTPParams* params, PTP_USB* ptp_usb, libusb_device* dev); |
-static short ptp_write_func (unsigned long,PTPDataHandler*,void *data,unsigned long*); |
-static short ptp_read_func (unsigned long,PTPDataHandler*,void *data,unsigned long*,int); |
-static int usb_get_endpoint_status(PTP_USB* ptp_usb, int ep, uint16_t* status); |
+static int init_ptp_usb(PTPParams* params, |
+ PTP_USB* ptp_usb, libusb_device* dev); |
+static short ptp_write_func(unsigned long, |
+ PTPDataHandler*, void *data, unsigned long*); |
+static short ptp_read_func (unsigned long, |
+ PTPDataHandler*, void *data, unsigned long*, int); |
+static int usb_get_endpoint_status(PTP_USB* ptp_usb, |
+ int ep, uint16_t* status); |
/** |
* Get a list of the supported USB devices. |
@@ -119,7 +130,8 @@ static int usb_get_endpoint_status(PTP_USB* ptp_usb, int ep, uint16_t* status); |
* @return 0 if the list was successfull retrieved, any other |
* value means failure. |
*/ |
-int LIBMTP_Get_Supported_Devices_List(LIBMTP_device_entry_t ** const devices, int * const numdevs) |
+int LIBMTP_Get_Supported_Devices_List(LIBMTP_device_entry_t ** const devices, |
+ int * const numdevs) |
{ |
*devices = (LIBMTP_device_entry_t *) &mtp_device_table; |
*numdevs = mtp_device_table_size; |
@@ -129,32 +141,38 @@ int LIBMTP_Get_Supported_Devices_List(LIBMTP_device_entry_t ** const devices, in |
static LIBMTP_error_number_t init_usb() |
{ |
+ static int libusb1_initialized = 0; |
+ |
/* |
* Some additional libusb debugging please. |
* We use the same level debug between MTP and USB. |
*/ |
+ if (libusb1_initialized) |
+ return LIBMTP_ERROR_NONE; |
+ |
if (libusb_init(NULL) < 0) { |
LIBMTP_ERROR("Libusb1 init failed\n"); |
return LIBMTP_ERROR_USB_LAYER; |
} |
+ libusb1_initialized = 1; |
+ |
if ((LIBMTP_debug & LIBMTP_DEBUG_USB) != 0) |
libusb_set_debug(NULL,9); |
return LIBMTP_ERROR_NONE; |
} |
/** |
- * Small recursive function to append a new usb_device to the linked list of |
- * USB MTP devices |
- * @param devlist dynamic linked list of pointers to usb devices with MTP |
- * properties, to be extended with new device. |
+ * Small recursive function to append a new usb_device to the linked |
+ * list of USB MTP devices |
+ * @param devlist dynamic linked list of pointers to usb devices with |
+ * MTP properties, to be extended with new device. |
* @param newdevice the new device to add. |
* @param bus_location bus for this device. |
* @return an extended array or NULL on failure. |
*/ |
static mtpdevice_list_t *append_to_mtpdevice_list(mtpdevice_list_t *devlist, |
libusb_device *newdevice, |
- |
uint32_t bus_location) |
{ |
mtpdevice_list_t *new_list_entry; |
@@ -292,8 +310,8 @@ static int probe_device_descriptor(libusb_device *dev, FILE *dumpfile) |
} |
/* |
- * Check for Still Image Capture class with PIMA 15740 protocol, |
- * also known as PTP |
+ * TODO: Check for Still Image Capture class with PIMA 15740 |
+ * protocol, also known as PTP |
*/ |
if (intf->bInterfaceClass == LIBUSB_CLASS_PTP |
&& intf->bInterfaceSubClass == 0x01 |
@@ -338,6 +356,7 @@ static int probe_device_descriptor(libusb_device *dev, FILE *dumpfile) |
LIBUSB_CLASS_MASS_STORAGE) { |
LIBMTP_INFO("avoid probing device using attached kernel interface\n"); |
libusb_free_config_descriptor(config); |
+ libusb_close(devh); |
return 0; |
} |
} |
@@ -571,13 +590,11 @@ int LIBMTP_Check_Specific_Device(int busno, int devno) |
nrofdevs = libusb_get_device_list (NULL, &devs); |
for (i = 0; i < nrofdevs ; i++ ) { |
- |
if (libusb_get_bus_number(devs[i]) != busno) |
- continue; |
+ continue; |
if (libusb_get_device_address(devs[i]) != devno) |
- continue; |
- |
- if (probe_device_descriptor(devs[i], NULL)) |
+ continue; |
+ if (probe_device_descriptor(devs[i], NULL)) |
return 1; |
} |
return 0; |
@@ -671,18 +688,7 @@ LIBMTP_error_number_t LIBMTP_Detect_Raw_Devices(LIBMTP_raw_device_t ** devices, |
} |
} |
if (!device_known) { |
- // This device is unknown to the developers |
- LIBMTP_ERROR("Device %d (VID=%04x and PID=%04x) is UNKNOWN.\n", |
- i, |
- desc.idVendor, |
- desc.idProduct); |
- LIBMTP_ERROR("Please report this VID/PID and the device model to the " |
- "libmtp development team\n"); |
- /* |
- * Trying to get iManufacturer or iProduct from the device at this |
- * point would require opening a device handle, that we don't want |
- * to do right now. (Takes time for no good enough reason.) |
- */ |
+ device_unknown(i, desc.idVendor, desc.idProduct); |
} |
// Save the location on the bus |
retdevs[i].bus_location = libusb_get_bus_number (dev->device); |
@@ -824,10 +830,25 @@ ptp_read_func ( |
int ret = 0; |
int xread; |
unsigned long curread = 0; |
- unsigned long written; |
unsigned char *bytes; |
int expect_terminator_byte = 0; |
- |
+ unsigned long usb_inep_maxpacket_size; |
+ unsigned long context_block_size_1; |
+ unsigned long context_block_size_2; |
+ uint16_t ptp_dev_vendor_id = ptp_usb->rawdevice.device_entry.vendor_id; |
+ |
+ //"iRiver" device special handling |
+ if (ptp_dev_vendor_id == 0x4102 || ptp_dev_vendor_id == 0x1006) { |
+ usb_inep_maxpacket_size = ptp_usb->inep_maxpacket; |
+ if (usb_inep_maxpacket_size == 0x400) { |
+ context_block_size_1 = CONTEXT_BLOCK_SIZE_1 - 0x200; |
+ context_block_size_2 = CONTEXT_BLOCK_SIZE_2 + 0x200; |
+ } |
+ else { |
+ context_block_size_1 = CONTEXT_BLOCK_SIZE_1; |
+ context_block_size_2 = CONTEXT_BLOCK_SIZE_2; |
+ } |
+ } |
// This is the largest block we'll need to read in. |
bytes = malloc(CONTEXT_BLOCK_SIZE); |
while (curread < size) { |
@@ -845,16 +866,21 @@ ptp_read_func ( |
expect_terminator_byte = 1; |
} |
} |
- else if (curread == 0) |
- // we are first packet, but not last packet |
- toread = CONTEXT_BLOCK_SIZE_1; |
- else if (toread == CONTEXT_BLOCK_SIZE_1) |
- toread = CONTEXT_BLOCK_SIZE_2; |
- else if (toread == CONTEXT_BLOCK_SIZE_2) |
- toread = CONTEXT_BLOCK_SIZE_1; |
+ else if (ptp_dev_vendor_id == 0x4102 || ptp_dev_vendor_id == 0x1006) { |
+ //"iRiver" device special handling |
+ if (curread == 0) |
+ // we are first packet, but not last packet |
+ toread = context_block_size_1; |
+ else if (toread == context_block_size_1) |
+ toread = context_block_size_2; |
+ else if (toread == context_block_size_2) |
+ toread = context_block_size_1; |
+ else |
+ LIBMTP_INFO("unexpected toread size 0x%04x, 0x%04x remaining bytes\n", |
+ (unsigned int) toread, (unsigned int) (size-curread)); |
+ } |
else |
- LIBMTP_INFO("unexpected toread size 0x%04x, 0x%04x remaining bytes\n", |
- (unsigned int) toread, (unsigned int) (size-curread)); |
+ toread = CONTEXT_BLOCK_SIZE; |
LIBMTP_USB_DEBUG("Reading in 0x%04lx bytes\n", toread); |
@@ -884,7 +910,7 @@ ptp_read_func ( |
xread--; |
} |
- int putfunc_ret = handler->putfunc(NULL, handler->priv, xread, bytes, &written); |
+ int putfunc_ret = handler->putfunc(NULL, handler->priv, xread, bytes); |
if (putfunc_ret != PTP_RC_OK) |
return putfunc_ret; |
@@ -958,7 +984,7 @@ ptp_write_func ( |
} |
while (curwrite < size) { |
unsigned long usbwritten = 0; |
- int xwritten; |
+ int xwritten = 0; |
towrite = size-curwrite; |
if (towrite > CONTEXT_BLOCK_SIZE) { |
@@ -1067,8 +1093,7 @@ memory_getfunc(PTPParams* params, void* private, |
static uint16_t |
memory_putfunc(PTPParams* params, void* private, |
- unsigned long sendlen, unsigned char *data, |
- unsigned long *putlen |
+ unsigned long sendlen, unsigned char *data |
) { |
PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)private; |
@@ -1078,7 +1103,6 @@ memory_putfunc(PTPParams* params, void* private, |
} |
memcpy (priv->data + priv->curoff, data, sendlen); |
priv->curoff += sendlen; |
- *putlen = sendlen; |
return PTP_RC_OK; |
} |
@@ -1140,7 +1164,7 @@ ptp_exit_recv_memory_handler (PTPDataHandler *handler, |
/* send / receive functions */ |
uint16_t |
-ptp_usb_sendreq (PTPParams* params, PTPContainer* req) |
+ptp_usb_sendreq (PTPParams* params, PTPContainer* req, int dataphase) |
{ |
uint16_t ret; |
PTPUSBBulkContainer usbreq; |
@@ -1150,7 +1174,7 @@ ptp_usb_sendreq (PTPParams* params, PTPContainer* req) |
char txt[256]; |
- (void) ptp_render_opcode (params, req->Code, sizeof(txt), txt); |
+ (void) ptp_render_ofc (params, req->Code, sizeof(txt), txt); |
LIBMTP_USB_DEBUG("REQUEST: 0x%04x, %s\n", req->Code, txt); |
/* build appropriate USB container */ |
@@ -1189,13 +1213,13 @@ ptp_usb_sendreq (PTPParams* params, PTPContainer* req) |
uint16_t |
ptp_usb_senddata (PTPParams* params, PTPContainer* ptp, |
- unsigned long size, PTPDataHandler *handler |
+ uint64_t size, PTPDataHandler *handler |
) { |
uint16_t ret; |
int wlen, datawlen; |
unsigned long written; |
PTPUSBBulkContainer usbdata; |
- uint32_t bytes_left_to_transfer; |
+ uint64_t bytes_left_to_transfer; |
PTPDataHandler memhandler; |
@@ -1257,6 +1281,10 @@ static uint16_t ptp_usb_getpacket(PTPParams *params, |
PTPDataHandler memhandler; |
uint16_t ret; |
unsigned char *x = NULL; |
+ unsigned long packet_size; |
+ PTP_USB *ptp_usb = (PTP_USB *) params->data; |
+ |
+ packet_size = ptp_usb->inep_maxpacket; |
/* read the header and potentially the first data */ |
if (params->response_packet_size > 0) { |
@@ -1270,7 +1298,7 @@ static uint16_t ptp_usb_getpacket(PTPParams *params, |
return PTP_RC_OK; |
} |
ptp_init_recv_memory_handler (&memhandler); |
- ret = ptp_read_func(PTP_USB_BULK_HS_MAX_PACKET_LEN_READ, &memhandler, params->data, rlen, 0); |
+ ret = ptp_read_func(packet_size, &memhandler, params->data, rlen, 0); |
ptp_exit_recv_memory_handler (&memhandler, &x, rlen); |
if (x) { |
memcpy (packet, x, *rlen); |
@@ -1284,7 +1312,6 @@ ptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler) |
{ |
uint16_t ret; |
PTPUSBBulkContainer usbdata; |
- unsigned long written; |
PTP_USB *ptp_usb = (PTP_USB *) params->data; |
int putfunc_ret; |
@@ -1326,12 +1353,11 @@ ptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler) |
break; |
} |
} |
- if (usbdata.length == 0xffffffffU) { |
+ if (rlen == ptp_usb->inep_maxpacket) { |
/* Copy first part of data to 'data' */ |
putfunc_ret = |
handler->putfunc( |
- params, handler->priv, rlen - PTP_USB_BULK_HDR_LEN, usbdata.payload.data, |
- &written |
+ params, handler->priv, rlen - PTP_USB_BULK_HDR_LEN, usbdata.payload.data |
); |
if (putfunc_ret != PTP_RC_OK) |
return putfunc_ret; |
@@ -1342,7 +1368,7 @@ ptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler) |
uint16_t xret; |
xret = ptp_read_func( |
- PTP_USB_BULK_HS_MAX_PACKET_LEN_READ, |
+ 0x20000000, |
handler, |
params->data, |
&readdata, |
@@ -1350,7 +1376,7 @@ ptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler) |
); |
if (xret != PTP_RC_OK) |
return xret; |
- if (readdata < PTP_USB_BULK_HS_MAX_PACKET_LEN_READ) |
+ if (readdata < 0x20000000) |
break; |
} |
return PTP_RC_OK; |
@@ -1401,14 +1427,13 @@ ptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler) |
putfunc_ret = |
handler->putfunc( |
params, handler->priv, rlen - PTP_USB_BULK_HDR_LEN, |
- usbdata.payload.data, |
- &written |
+ usbdata.payload.data |
); |
if (putfunc_ret != PTP_RC_OK) |
return putfunc_ret; |
if (FLAG_NO_ZERO_READS(ptp_usb) && |
- len+PTP_USB_BULK_HDR_LEN == PTP_USB_BULK_HS_MAX_PACKET_LEN_READ) { |
+ len+PTP_USB_BULK_HDR_LEN == ptp_usb->inep_maxpacket) { |
LIBMTP_USB_DEBUG("Reading in extra terminating byte\n"); |
@@ -1423,8 +1448,8 @@ ptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler) |
ptp_usb->timeout); |
if (result != 1) |
- LIBMTP_INFO("Could not read in extra byte for PTP_USB_BULK_HS_MAX_PACKET_LEN_READ long file, return value 0x%04x\n", result); |
- } else if (len+PTP_USB_BULK_HDR_LEN == PTP_USB_BULK_HS_MAX_PACKET_LEN_READ && params->split_header_data == 0) { |
+ LIBMTP_INFO("Could not read in extra byte for %d byte long file, return value 0x%04x\n", ptp_usb->inep_maxpacket, result); |
+ } else if (len+PTP_USB_BULK_HDR_LEN == ptp_usb->inep_maxpacket && params->split_header_data == 0) { |
int zeroresult = 0, xread; |
unsigned char zerobyte = 0; |
@@ -1535,12 +1560,14 @@ ptp_usb_event (PTPParams* params, PTPContainer* event, int wait) |
int result, xread; |
unsigned long rlen; |
PTPUSBEventContainer usbevent; |
- PTP_USB *ptp_usb = (PTP_USB *)(params->data); |
+ PTP_USB *ptp_usb; |
memset(&usbevent,0,sizeof(usbevent)); |
if ((params==NULL) || (event==NULL)) |
return PTP_ERROR_BADPARAM; |
+ ptp_usb = (PTP_USB *)(params->data); |
+ |
ret = PTP_RC_OK; |
switch(wait) { |
case PTP_EVENT_CHECK: |
@@ -1613,6 +1640,109 @@ ptp_usb_event_wait (PTPParams* params, PTPContainer* event) { |
return ptp_usb_event (params, event, PTP_EVENT_CHECK); |
} |
+static void |
+ptp_usb_event_cb (struct libusb_transfer *t) { |
+ struct ptp_event_cb_data *data = t->user_data; |
+ PTPParams *params = data->params; |
+ PTPUSBEventContainer *usbevent = (void *)t->buffer; |
+ PTPContainer event = {0,}; |
+ uint16_t code; |
+ |
+ switch (t->status) { |
+ case LIBUSB_TRANSFER_COMPLETED: |
+ if (t->actual_length < 8) { |
+ libusb_glue_error (params, |
+ "PTP: reading event an short read of %ld bytes occurred\n", |
+ t->actual_length); |
+ code = PTP_ERROR_IO; |
+ } else { |
+ event.Code=dtoh16(usbevent->code); |
+ event.SessionID=params->session_id; |
+ event.Transaction_ID=dtoh32(usbevent->trans_id); |
+ event.Param1=dtoh32(usbevent->param1); |
+ event.Param2=dtoh32(usbevent->param2); |
+ event.Param3=dtoh32(usbevent->param3); |
+ code = PTP_RC_OK; |
+ } |
+ break; |
+ case LIBUSB_TRANSFER_TIMED_OUT: |
+ code = PTP_ERROR_TIMEOUT; |
+ break; |
+ case LIBUSB_TRANSFER_CANCELLED: |
+ code = PTP_ERROR_CANCEL; |
+ break; |
+ case LIBUSB_TRANSFER_STALL: |
+ code = PTP_ERROR_DATA_EXPECTED; |
+ break; |
+ case LIBUSB_TRANSFER_ERROR: |
+ case LIBUSB_TRANSFER_NO_DEVICE: |
+ case LIBUSB_TRANSFER_OVERFLOW: |
+ default: |
+ code = PTP_ERROR_IO; |
+ break; |
+ } |
+ if (code != PTP_RC_OK) { |
+ libusb_glue_error (params, |
+ "PTP: reading event an error 0x%02x occurred\n", |
+ t->status); |
+ } |
+ data->cb(params, code, &event, data->user_data); |
+ free(data); |
+} |
+ |
+uint16_t |
+ptp_usb_event_async (PTPParams* params, PTPEventCbFn cb, void *user_data) { |
+ PTP_USB *ptp_usb; |
+ PTPUSBEventContainer *usbevent; |
+ struct ptp_event_cb_data *data; |
+ struct libusb_transfer *t; |
+ int ret; |
+ |
+ if (params == NULL) { |
+ return PTP_ERROR_BADPARAM; |
+ } |
+ |
+ usbevent = calloc(1, sizeof(*usbevent)); |
+ if (usbevent == NULL) { |
+ return PTP_ERROR_IO; |
+ } |
+ |
+ data = malloc(sizeof(*data)); |
+ if (data == NULL) { |
+ free(usbevent); |
+ return PTP_ERROR_IO; |
+ } |
+ |
+ t = libusb_alloc_transfer(0); |
+ if (t == NULL) { |
+ free(data); |
+ free(usbevent); |
+ return PTP_ERROR_IO; |
+ } |
+ |
+ data->cb = cb; |
+ data->user_data = user_data; |
+ data->params = params; |
+ |
+ ptp_usb = (PTP_USB *)(params->data); |
+ libusb_fill_interrupt_transfer(t, ptp_usb->handle, ptp_usb->intep, |
+ (unsigned char *)usbevent, sizeof(*usbevent), |
+ ptp_usb_event_cb, data, 0); |
+ t->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER; |
+ |
+ ret = libusb_submit_transfer(t); |
+ return ret == 0 ? PTP_RC_OK : PTP_ERROR_IO; |
+} |
+ |
+/** |
+ * Trivial wrapper around the most generic libusb method for polling for events. |
+ * Can be used to drive asynchronous event detection. |
+ */ |
+int LIBMTP_Handle_Events_Timeout_Completed(struct timeval *tv, int *completed) { |
+ /* Pass NULL for context as libmtp always uses the default context */ |
+ return libusb_handle_events_timeout_completed(NULL, tv, completed); |
+} |
+ |
uint16_t |
ptp_usb_control_cancel_request (PTPParams *params, uint32_t transactionid) { |
PTP_USB *ptp_usb = (PTP_USB *)(params->data); |
@@ -1678,11 +1808,22 @@ static int init_ptp_usb(PTPParams* params, PTP_USB* ptp_usb, libusb_device* dev) |
* Check if the config is set to something else than what we want |
* to use. Only set the configuration if we absolutely have to. |
* Also do not bail out if we fail. |
+ * |
+ * Note that Darwin will not set the configuration for vendor-specific |
+ * devices so we need to go in and set it. |
*/ |
ret = libusb_get_active_config_descriptor(dev, &config); |
if (ret != LIBUSB_SUCCESS) { |
perror("libusb_get_active_config_descriptor(1) failed"); |
- return -1; |
+ fprintf(stderr, "no active configuration, trying to set configuration\n"); |
+ if (libusb_set_configuration(device_handle, ptp_usb->config) != LIBUSB_SUCCESS) { |
+ perror("libusb_set_configuration() failed, continuing anyway..."); |
+ } |
+ ret = libusb_get_active_config_descriptor(dev, &config); |
+ if (ret != LIBUSB_SUCCESS) { |
+ perror("libusb_get_active_config_descriptor(2) failed"); |
+ return -1; |
+ } |
} |
if (config->bConfigurationValue != ptp_usb->config) { |
fprintf(stderr, "desired configuration different from current, trying to set configuration\n"); |
@@ -1798,7 +1939,7 @@ static void clear_stall(PTP_USB* ptp_usb) |
perror("outep: usb_get_endpoint_status()"); |
} else if (status) { |
LIBMTP_INFO("Clearing stall on OUT endpoint\n"); |
- ret = libusb_clear_halt (ptp_usb->handle, ptp_usb->outep); |
+ ret = libusb_clear_halt(ptp_usb->handle, ptp_usb->outep); |
if (ret != LIBUSB_SUCCESS) { |
perror("usb_clear_stall_feature()"); |
} |
@@ -1807,24 +1948,6 @@ static void clear_stall(PTP_USB* ptp_usb) |
/* TODO: do we need this for INTERRUPT (ptp_usb->intep) too? */ |
} |
-static void clear_halt(PTP_USB* ptp_usb) |
-{ |
- int ret; |
- |
- ret = libusb_clear_halt(ptp_usb->handle,ptp_usb->inep); |
- if (ret<0) { |
- perror("usb_clear_halt() on IN endpoint"); |
- } |
- ret = libusb_clear_halt(ptp_usb->handle,ptp_usb->outep); |
- if (ret<0) { |
- perror("usb_clear_halt() on OUT endpoint"); |
- } |
- ret = libusb_clear_halt(ptp_usb->handle,ptp_usb->intep); |
- if (ret<0) { |
- perror("usb_clear_halt() on INTERRUPT endpoint"); |
- } |
-} |
- |
static void close_usb(PTP_USB* ptp_usb) |
{ |
if (!FLAG_NO_RELEASE_INTERFACE(ptp_usb)) { |
@@ -1839,12 +1962,6 @@ static void close_usb(PTP_USB* ptp_usb) |
* STALL is persistant or not). |
*/ |
clear_stall(ptp_usb); |
- // Clear halts on any endpoints |
- clear_halt(ptp_usb); |
- // Added to clear some stuff on the OUT endpoint |
- // TODO: is this good on the Mac too? |
- // HINT: some devices may need that you comment these two out too. |
- libusb_clear_halt(ptp_usb->handle, ptp_usb->outep); |
libusb_release_interface(ptp_usb->handle, (int) ptp_usb->interface); |
} |
if (FLAG_FORCE_RESET_ON_CLOSE(ptp_usb)) { |
@@ -1886,12 +2003,11 @@ static int find_interface_and_endpoints(libusb_device *dev, |
struct libusb_config_descriptor *config; |
ret = libusb_get_config_descriptor(dev, i, &config); |
- if (ret != 0) |
+ if (ret != LIBUSB_SUCCESS) |
continue; |
*conf = config->bConfigurationValue; |
- if (ret != LIBUSB_SUCCESS) continue; |
// Loop over each configurations interfaces |
for (j = 0; j < config->bNumInterfaces; j++) { |
uint8_t k, l; |
@@ -2031,6 +2147,7 @@ LIBMTP_error_number_t configure_usb_device(LIBMTP_raw_device_t *device, |
if (err) { |
libusb_free_device_list (devs, 0); |
+ free (ptp_usb); |
LIBMTP_ERROR("LIBMTP PANIC: Unable to find interface & endpoints of device\n"); |
return LIBMTP_ERROR_CONNECTING; |
} |
@@ -2040,6 +2157,7 @@ LIBMTP_error_number_t configure_usb_device(LIBMTP_raw_device_t *device, |
/* Attempt to initialize this device */ |
if (init_ptp_usb(params, ptp_usb, ldevice) < 0) { |
+ free (ptp_usb); |
LIBMTP_ERROR("LIBMTP PANIC: Unable to initialize device\n"); |
libusb_free_device_list (devs, 0); |
return LIBMTP_ERROR_CONNECTING; |
@@ -2058,6 +2176,7 @@ LIBMTP_error_number_t configure_usb_device(LIBMTP_raw_device_t *device, |
if(init_ptp_usb(params, ptp_usb, ldevice) <0) { |
LIBMTP_ERROR("LIBMTP PANIC: Could not init USB on second attempt\n"); |
libusb_free_device_list (devs, 0); |
+ free (ptp_usb); |
return LIBMTP_ERROR_CONNECTING; |
} |
@@ -2065,6 +2184,7 @@ LIBMTP_error_number_t configure_usb_device(LIBMTP_raw_device_t *device, |
if ((ret = ptp_opensession(params, 1)) == PTP_ERROR_IO) { |
LIBMTP_ERROR("LIBMTP PANIC: failed to open session on second attempt\n"); |
libusb_free_device_list (devs, 0); |
+ free (ptp_usb); |
return LIBMTP_ERROR_CONNECTING; |
} |
} |
@@ -2082,6 +2202,7 @@ LIBMTP_error_number_t configure_usb_device(LIBMTP_raw_device_t *device, |
ret); |
libusb_release_interface(ptp_usb->handle, ptp_usb->interface); |
libusb_free_device_list (devs, 0); |
+ free (ptp_usb); |
return LIBMTP_ERROR_CONNECTING; |
} |