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