diff options
-rw-r--r-- | TODO | 6 | ||||
-rw-r--r-- | configure.ac | 11 | ||||
-rw-r--r-- | src/Makefile.am | 26 | ||||
-rw-r--r-- | src/README | 13 | ||||
-rw-r--r-- | src/libmtp.c | 19 | ||||
-rw-r--r-- | src/libusb-glue.c | 26 | ||||
-rw-r--r-- | src/libusb-glue.h | 2 |
7 files changed, 84 insertions, 19 deletions
@@ -0,0 +1,6 @@ +TODO file: +---------- + +* Add all thinkable codecs. + +* Add a function that will list the available codecs for a certain device. diff --git a/configure.ac b/configure.ac index fd26671..abfa3ee 100644 --- a/configure.ac +++ b/configure.ac @@ -88,11 +88,16 @@ AC_CHECK_FUNCS(basename memset select strdup strerror strrchr strtoul usleep) CFLAGS="$CFLAGS -Wall -Wmissing-prototypes" # Output files -dnl Create a stdint.h-like file containing size-specific integer definitions -dnl that will always be available + +# Create a stdint.h-like file containing size-specific integer definitions +# that will always be available. The <stdint.h> file is required by the +# library, but we provide this anyway because the libptp2 stuff wants this +# file. AX_NEED_STDINT_H([src/libptp-stdint.h]) -dnl Create a header file containing NetBSD-style byte swapping macros +# Create a header file containing NetBSD-style byte swapping macros. +# This m4 macros has caused severe pain, I am considering creating a +# hard-coded byte swapper that will be eternally portable. AC_NEED_BYTEORDER_H(src/libptp-endian.h) AC_CONFIG_FILES([src/libmtp.h doc/Doxyfile Makefile doc/Makefile src/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index bfcaeb9..b397564 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,10 +5,28 @@ libmtp_la_SOURCES=libmtp.c unicode.c unicode.h util.c util.h \ include_HEADERS=libmtp.h EXTRA_DIST=libmtp.h.in libmtp.sym -# This is the version of the *library interface*, not the revision -# of libmtp itself. Do not change this unless you're absolutely -# certain of what the difference is. (See the libtool manual, -# section 6.3 (http://www.gnu.org/software/libtool/manual.html) +# --------------------------------------------------------------------------- +# Advanced information about versioning: +# * "Writing shared libraries" by Mike Hearn +# http://navi.cx/~mike/writing-shared-libraries.html +# * libtool.info chapter "Versioning" +# * libtool.info chapter "Updating library version information" +# --------------------------------------------------------------------------- +# Versioning: +# - CURRENT (Major): Increment if the interface has changes. AGE is always +# *changed* at the same time. +# - AGE (Micro): Increment if any interfaces have been added; set to 0 +# if any interfaces have been removed. Removal has +# precedence over adding, so set to 0 if both happened. +# It denotes upward compatibility. +# - REVISION (Minor): Increment any time the source changes; set to +# 0 if you incremented CURRENT. +# +# To summarize. Any interface *change* increment CURRENT. If that interface +# change does not break upward compatibility (ie it is an addition), +# increment AGE, Otherwise AGE is reset to 0. If CURRENT has changed, +# REVISION is set to 0, otherwise REVISION is incremented. +# --------------------------------------------------------------------------- CURRENT=0 REVISION=0 AGE=0 @@ -1,5 +1,18 @@ Lots of docs to follow... +KERNEL BUG ON LINUX +------------------- + +Linux 2.6.16 is generally speaking required to use any MTP +device under USB 2.0. This is because the EHCI driver +previously did not support zero-length writes to endpoints. + +It should work in most cases however, or if you connect it +to an UHCI/OHCI port instead (yielding lower speed). But +please just use a recent kernel. + + + RELATION TO LIBPTP2 ------------------- diff --git a/src/libmtp.c b/src/libmtp.c index c11faec..6fe02c8 100644 --- a/src/libmtp.c +++ b/src/libmtp.c @@ -1006,7 +1006,9 @@ static int send_file_object(LIBMTP_mtpdevice_t *device, uint16_t ret; uint8_t *buffer; uint64_t remain; + int last_chunk_size = 0; // Size of the last chunk written to the OUT endpoint PTPParams *params = (PTPParams *) device->params; + PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo; // Nullify and configure PTP container memset(&ptp, 0, sizeof(ptp)); @@ -1077,6 +1079,8 @@ static int send_file_object(LIBMTP_mtpdevice_t *device, return -1; } remain -= (uint64_t) readsize; + // This is useful to keep track of last write + last_chunk_size = readsize; } if (callback != NULL) { @@ -1085,12 +1089,15 @@ static int send_file_object(LIBMTP_mtpdevice_t *device, (void) callback(size, size, data); } - // Signal to USB that this is the last transfer if the last chunk - // was exactly as large as the buffer. This was part of Richards - // source code but apparently has some problems on Linux for some reason, - // could be that libusb on Linux intrinsically adds the final zero-length - // transfer call. - if (size % MTP_DEVICE_BUF_SIZE == 0) { + /* + * Signal to USB that this is the last transfer if the last chunk + * was exactly as large as the buffer. + * + * On Linux you need kernel 2.6.16 or newer for this to work under + * USB 2.0 since the EHCI driver did not support zerolength writes + * until then. (Using a UHCI port should be OK though.) + */ + if (last_chunk_size == ptp_usb->outep_maxpacket) { ret = params->write_func(NULL, 0, params->data); if (ret!=PTP_RC_OK) { printf("send_file_object: error writing last zerolen data chunk for USB termination\n"); diff --git a/src/libusb-glue.c b/src/libusb-glue.c index fa1c449..35ba363 100644 --- a/src/libusb-glue.c +++ b/src/libusb-glue.c @@ -51,9 +51,11 @@ #endif /* - * MTP device list + * MTP device list, trying real bad to get all devices into + * this list by stealing from everyone I know. */ static const LIBMTP_device_entry_t mtp_device_table[] = { + /* Creative devices */ { "Creative Zen Vision", 0x041e, 0x411f, NULL }, { "Creative Portable Media Center", 0x041e, 0x4123, NULL }, { "Creative Zen Xtra (MTP mode)", 0x041e, 0x4128, NULL }, @@ -64,9 +66,19 @@ static const LIBMTP_device_entry_t mtp_device_table[] = { { "Creative Zen MicroPhoto", 0x041e, 0x413c, NULL }, { "Creative Zen Sleek Photo", 0x041e, 0x413d, NULL }, { "Creative Zen Vision:M", 0x041e, 0x413e, NULL }, + /* + * Copied in from libgphoto2's libptp2 adaption "library.c" + * carefully trying to pick only the MTP devices. + * Greetings to Marcus Meissner! (we should merge our + * projects some day...) + */ + { "Philipps HDD6320", 0x041e, 0x01eb, NULL}, { "iRiver T10", 0x4102, 0x1113, NULL }, + { "iRiver U10", 0x4102, 0x1116, NULL }, { "iRiver T10", 0x4102, 0x1117, NULL }, - { "iRiver T30", 0x4102, 0x1119, NULL } + { "iRiver T20", 0x4102, 0x1118, NULL }, + { "iRiver T30", 0x4102, 0x1119, NULL }, + { "Toshiba Gigabeat", 0x0930, 0x000c, NULL} }; static const int mtp_device_table_size = sizeof(mtp_device_table) / sizeof(LIBMTP_device_entry_t); @@ -74,7 +86,7 @@ int ptpcam_usb_timeout = USB_TIMEOUT; void close_usb(PTP_USB* ptp_usb, uint8_t interfaceNumber); struct usb_device* find_device (int busn, int devicen, short force); -void find_endpoints(struct usb_device *dev, int* inep, int* outep, int* intep); +void find_endpoints(struct usb_device *dev, int* inep, int* inep_maxpacket, int* outep, int* outep_maxpacket, int* intep); void clear_stall(PTP_USB* ptp_usb); void init_ptp_usb (PTPParams* params, PTP_USB* ptp_usb, struct usb_device* dev); static short ptp_write_func (unsigned char *bytes, unsigned int size, void *data); @@ -315,7 +327,7 @@ uint16_t connect_first_device(PTPParams *params, PTP_USB *ptp_usb, uint8_t *inte ep = dev->config->interface->altsetting->endpoint; n=dev->config->interface->altsetting->bNumEndpoints; - find_endpoints(dev,&(ptp_usb->inep),&(ptp_usb->outep),&(ptp_usb->intep)); + find_endpoints(dev,&(ptp_usb->inep),&(ptp_usb->inep_maxpacket),&(ptp_usb->outep),&(ptp_usb->outep_maxpacket),&(ptp_usb->intep)); init_ptp_usb(params, ptp_usb, dev); ret = ptp_opensession(params,1); @@ -344,7 +356,7 @@ uint16_t connect_first_device(PTPParams *params, PTP_USB *ptp_usb, uint8_t *inte return PTP_CD_RC_NO_DEVICES; } -void find_endpoints(struct usb_device *dev, int* inep, int* outep, int* intep) +void find_endpoints(struct usb_device *dev, int* inep, int* inep_maxpacket, int* outep, int *outep_maxpacket, int* intep) { int i,n; struct usb_endpoint_descriptor *ep; @@ -358,10 +370,12 @@ void find_endpoints(struct usb_device *dev, int* inep, int* outep, int* intep) USB_ENDPOINT_DIR_MASK) { *inep=ep[i].bEndpointAddress; + *inep_maxpacket=ep[i].wMaxPacketSize; } if ((ep[i].bEndpointAddress&USB_ENDPOINT_DIR_MASK)==0) { *outep=ep[i].bEndpointAddress; + *inep_maxpacket=ep[i].wMaxPacketSize; } } else if (ep[i].bmAttributes==USB_ENDPOINT_TYPE_INTERRUPT){ if ((ep[i].bEndpointAddress&USB_ENDPOINT_DIR_MASK)== @@ -386,7 +400,7 @@ int open_device (int busn, int devn, short force, PTP_USB *ptp_usb, PTPParams *p "bus/dev numbers\n"); exit(-1); } - find_endpoints(*dev,&ptp_usb->inep,&ptp_usb->outep,&ptp_usb->intep); + find_endpoints(*dev,&ptp_usb->inep,&ptp_usb->inep_maxpacket,&ptp_usb->outep,&ptp_usb->outep_maxpacket,&ptp_usb->intep); init_ptp_usb(params, ptp_usb, *dev); if (ptp_opensession(params,1)!=PTP_RC_OK) { diff --git a/src/libusb-glue.h b/src/libusb-glue.h index d62710f..9ffb5a6 100644 --- a/src/libusb-glue.h +++ b/src/libusb-glue.h @@ -20,7 +20,9 @@ typedef struct _PTP_USB PTP_USB; struct _PTP_USB { usb_dev_handle* handle; int inep; + int inep_maxpacket; int outep; + int outep_maxpacket; int intep; }; |