summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Walleij <triad@df.lth.se>2006-03-28 09:45:00 +0000
committerLinus Walleij <triad@df.lth.se>2006-03-28 09:45:00 +0000
commite8c5464bae7180c951e6bbb8238d85f8bce3c5c7 (patch)
tree7c3dbfba1a4ae782fa6d22e3ac59eb81905330fc
parent6fd2f081a516019d7f37ec82ac9eb100cf3a17b7 (diff)
downloadlibmtp-e8c5464bae7180c951e6bbb8238d85f8bce3c5c7.tar.gz
Fixes from libgphoto2
-rw-r--r--TODO6
-rw-r--r--configure.ac11
-rw-r--r--src/Makefile.am26
-rw-r--r--src/README13
-rw-r--r--src/libmtp.c19
-rw-r--r--src/libusb-glue.c26
-rw-r--r--src/libusb-glue.h2
7 files changed, 84 insertions, 19 deletions
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..bbb7e2c
--- /dev/null
+++ b/TODO
@@ -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
diff --git a/src/README b/src/README
index a4b8e35..33fb827 100644
--- a/src/README
+++ b/src/README
@@ -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;
};