[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[coldsync-hackers] Patch for USB Sony Clie on FreeBSD 4.5-STABLE




First of all I have a Sony Clie PEG-NR70/J which is a Japanese model, but I
doubt that makes any difference. This patch should also get USB Sony Clie's
working on earlier versions of FreeBSD, but I haven't tested that, so who
knows.

There were four problems that I had to fix to get it to work. The first
three were relatively straight forward, but the fourth I don't understand.

1. About 2 months ago they changed the naming conventions for all the USB
structures. So wherever you had udi.vendorNo, you now have to put
udi.udi_vendorNo. I added a check to configure to figure which one you have
and it sets a define accordingly. Then I use that define to pick a set of
macros to use. Then I used those macros to access the structure members. So
it should all work on older versions of FreeBSD as well.

2. I'm not sure when this happened, but now you need to send a
fcntl(USB_DISCOVER) on the USB bus if you want FreeBSD to connect the newly
attached USB device to /dev/ugen0. The man page on /dev/usb also explained
that you can use poll to check and see if any new devices have joined the
hub. This is a slightly nicer solution then continuously trying to open
/dev/ugen0, so I wrote the new opening routine to poll /dev/usb0 for the
device. I'm not sure whether this technique works on older versions of
FreeBSD so if you have a version of FreeBSD before the USB structure
renaming, it uses the old methodolgy.

3. The Sony Clie does not like the usbRequestVendorGetBytesAvailable
request. If you make that request, it wrecks the whole USB bus and you can't
attach the Clie again until you reboot. So now if coldsync detects the
vendor as Sony, it doesn't send that request. It seems to work fine without
it.

4. I had a problem with the 'usb_read' function that I don't understand.
It would get to the part where it calls DlpReadDBList. This would send off a
request for the DB list to the Clie. It would get the header back for the
reply which says there are 64 bytes in the packet. It would then call read
for 1024 bytes on the ugen0.2 device. The comment in the source code says it
needs to buffer because there is no buffer in the usb device kernel. For a
bunch of reads up to that point, it worked fine. But at that point, if it
tried to read 1024 bytes it would just hang. I changed it to just read the
number of bytes requested and that fixed the problem. I also tried smaller
buffers, but that didn't work either. I suspect it is some sort of timing
problem, but it seems a little strange to me.

Anyway, this patch makes coldsync work for me. If anyone has any suggestions
on the 'usb_read' issue, I'd like to hear them.

Here's the setup in my config file:

listen usb {
        device: "/dev/ugen0";
	protocol: net;
}

Here's the patch:

Index: config.h.in
===================================================================
RCS file: /var/lib/cvs/coldsync/config.h.in,v
retrieving revision 1.40
diff -u -r1.40 config.h.in
--- config.h.in	12 Oct 2001 02:14:54 -0000	1.40
+++ config.h.in	13 Apr 2002 06:42:37 -0000
@@ -29,7 +29,9 @@
 #undef pid_t
 
 /* Define to `int' if <signal.h> doesn't define return value for signal() */
-#undef RETSIGTYPE	/* int */
+#ifndef RETSIGTYPE
+#define RETSIGTYPE %%RETSIGTYPE%%
+#endif /* !RETSIGTYPE */
 
 /* Define to `unsigned' if <sys/types.h> doesn't define.  */
 #undef size_t
@@ -206,6 +208,9 @@
 
 /* Define if you want USB support for the Handspring Visor */
 #undef WITH_USB
+
+/* Define if you are using a version of FreeBSD after the USB rename */
+#undef AFTER_FREEBSD_USB_RENAME
 
 /* Name of package */
 #undef PACKAGE
Index: configure.in
===================================================================
RCS file: /var/lib/cvs/coldsync/configure.in,v
retrieving revision 1.142
diff -u -r1.142 configure.in
--- configure.in	18 Mar 2002 11:18:24 -0000	1.142
+++ configure.in	13 Apr 2002 06:42:38 -0000
@@ -512,10 +512,17 @@
 	AC_TRY_COMPILE(dnl
 		[#include <dev/usb/usb.h>],dnl
 		[struct usb_device_info udi;
-		 udi.vendorNo = 0x082d;],dnl
+		 udi.udi_vendorNo = 0x082d;],dnl
 		[AC_DEFINE_UNQUOTED(WITH_USB)
+		AC_DEFINE_UNQUOTED(AFTER_FREEBSD_USB_RENAME)
 		AC_MSG_RESULT(yes)],dnl
-		[AC_MSG_RESULT(no)])
+		AC_TRY_COMPILE(dnl
+			[#include <dev/usb/usb.h>],dnl
+			[struct usb_device_info udi;
+			 udi.vendorNo = 0x082d;],dnl
+			[AC_DEFINE_UNQUOTED(WITH_USB)
+			AC_MSG_RESULT(yes)],dnl
+			[AC_MSG_RESULT(no)]))
 fi
 
 # Don't build the Perl stuff
Index: libpconn/PConnection_usb.c
===================================================================
RCS file: /var/lib/cvs/coldsync/libpconn/PConnection_usb.c,v
retrieving revision 1.34
diff -u -r1.34 PConnection_usb.c
--- libpconn/PConnection_usb.c	10 Dec 2001 07:29:17 -0000	1.34
+++ libpconn/PConnection_usb.c	13 Apr 2002 06:42:39 -0000
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <poll.h>
 
 #if STDC_HEADERS
 # include <string.h>		/* For memcpy() et al. */
@@ -46,14 +47,40 @@
 #include "pconn/palm_errno.h"
 #include "pconn/netsync.h"
 
+#define IOBUF_LEN 1024
+
 struct usb_data {
-	unsigned char iobuf[1024];	/* XXX - Is there anything
-					 * magical about 1024? Make
-					 * this a cpp symbol */
+	unsigned char iobuf[IOBUF_LEN];
 	unsigned char *iobufp;
 	int iobuflen;
 };
 
+#ifdef AFTER_FREEBSD_USB_RENAME
+#define USB_UDI_VENDOR(udi) udi.udi_vendor
+#define USB_UDI_VENDOR_NO(udi) udi.udi_vendorNo
+#define USB_UDI_PRODUCT(udi) udi.udi_product
+#define USB_UDI_PRODUCT_NO(udi) udi.udi_productNo
+#define USB_UDI_ADDR(udi) udi.udi_addr
+#define USB_UDI_RELEASE(udi) udi.udi_release
+
+#define USB_UCR_REQUEST(ucr) ucr.ucr_request
+#define USB_UCR_DATA(ucr) ucr.ucr_data
+#define USB_UCR_FLAGS(ucr) ucr.ucr_flags
+#define USB_UCR_ACTLEN(ucr) ucr.ucr_actlen
+#else /* AFTER_FREEBSD_USB_RENAME */
+#define USB_UDI_VENDOR(udi) udi.vendor
+#define USB_UDI_VENDOR_NO(udi) udi.vendorNo
+#define USB_UDI_PRODUCT(udi) udi.product
+#define USB_UDI_PRODUCT_NO(udi) udi.productNo
+#define USB_UDI_ADDR(udi) udi.addr
+#define USB_UDI_RELEASE(udi) udi.release
+
+#define USB_UCR_REQUEST(ucr) ucr.request
+#define USB_UCR_DATA(ucr) ucr.data
+#define USB_UCR_FLAGS(ucr) ucr.flags
+#define USB_UCR_ACTLEN(ucr) ucr.actlen
+#endif /* AFTER_FREEBSD_USB_RENAME */
+
 
 /*
  *  Description of the Handspring Visor vendor specific USB
@@ -100,6 +127,7 @@
  */
 #define	HANDSPRING_VENDOR_ID	0x082d
 #define PALM_VENDOR_ID		0x0830
+#define SONY_VENDOR_ID		0x054c
 
 static char *hs_usb_functions[] = {
 	"Generic",
@@ -184,7 +212,7 @@
 			}
 
 			u->iobufp = u->iobuf;
-			u->iobuflen = read(p->fd, u->iobufp, sizeof(u->iobuf));
+			u->iobuflen = read(p->fd, u->iobufp, (len > IOBUF_LEN) ? IOBUF_LEN : len);
 			if (u->iobuflen < 0) {
 				perror("usb read");
 				return u->iobuflen;
@@ -333,6 +361,123 @@
 	return 0;
 }
 
+#ifdef AFTER_FREEBSD_USB_RENAME
+int
+open_usb_device(const char* device, 
+		const unsigned short flags)
+{
+	int usb_bus = -1;
+	int usb_dev = -1;
+	int result;
+	int error = 0;
+	time_t start_time;
+	time_t remaining_time;
+	struct pollfd poll_fds;
+
+	usb_bus = open("/dev/usb0", O_RDWR | O_BINARY);
+	if (usb_bus < 0) {
+		fprintf(stderr,
+			_("%s: Can't open the USB bus.\n"),
+			"open_usb_device");
+		perror("open");
+		return -1;
+	}
+
+	start_time = time(NULL);
+	remaining_time = 30;
+	while (remaining_time > 0) {
+		result = ioctl(usb_bus, USB_DISCOVER, NULL);
+		if (result < 0) {
+			fprintf(stderr, _("%s: Error running discover on usb bus\n"), "open_usb_device");
+			perror("ioctl(USB_DISCOVER)");
+			error = 1;
+			break;
+		}
+
+		usb_dev = open(device, O_RDWR);
+		if (usb_dev < 0 && errno != ENXIO && 
+		    ((errno == ENOENT) && !((flags & PCONNFL_TRANSIENT)))) {
+			fprintf(stderr, _("%s: Error opening usb device\n"), "open_usb_device");
+			perror("open");
+			error = 1;
+			break;
+		}
+		if (usb_dev > 0) {
+			break;
+		}
+
+		poll_fds.fd = usb_bus;
+		poll_fds.events = POLLRDNORM;
+		poll_fds.revents = POLLRDNORM;
+
+		result = poll(&poll_fds, 1, remaining_time * 1000);
+		if (result < 0) {
+			fprintf(stderr, _("%s: Error waiting for signal on usb bus.\n"), "open_usb_device");
+			perror("poll");
+			error = 1;
+			break;
+		}
+		remaining_time = start_time + 30 - time(NULL);
+	}
+
+	if (!error && usb_dev < 0) {
+		fprintf(stderr, _("%s: Timeout waiting for usb device.\n"), "open_usb_device");
+		error = 1;
+	}
+
+	if (usb_bus >= 0) {
+		close(usb_bus);
+	}
+
+	if (error && usb_dev >= 0) {
+		close(usb_dev);
+		usb_dev = -1;
+	}
+
+	return usb_dev;
+}
+
+#else /* AFTER_FREEBSD_USB_RENAME */
+int
+open_usb_device(const char* device, 
+		const unsigned short flags)
+{
+	int i;
+	int usb_ep0 = -1;
+
+	for (i = 0; i < 30; i++) {
+		if ((usb_ep0 = open(device, O_RDWR | O_BINARY)) >= 0) 
+                               /* The O_BINARY flag is rather bogus, since
+                                * the only relevant platform that uses it
+                                * is Windows, and this USB code only works
+                                * under FreeBSD. But hey, it doesn't cost
+				* anything, and it makes things
+				* consistent.
+				*/
+			break;
+
+		IO_TRACE(1)
+			perror(device);
+
+		if ((errno == ENOENT) && ((flags & PCONNFL_TRANSIENT) != 0))
+			/* Just ignore this error */
+			;
+		else if (errno != ENXIO) {
+			fprintf(stderr, _("Error: Can't open \"%s\".\n"),
+				device);
+			perror("open");
+			/*  If some other error, don't bother waiting
+			 *  for the timeout to expire.
+			 */
+			break;
+		}
+		sleep(1);
+	}
+
+	return usb_ep0;
+}
+#endif /* AFTER_FREEBSD_USB_RENAME */
+
 int
 pconn_usb_open(PConnection *pconn,
 	       const char *device,
@@ -439,34 +584,7 @@
 	 *  you'll get an ENXIO until the device has been inserted
 	 *  on the USB bus.
 	 */
-	for (i = 0; i < 30; i++) {
-		if ((usb_ep0 = open(device, O_RDWR | O_BINARY)) >= 0) 
-				/* The O_BINARY flag is rather bogus, since
-				 * the only relevant platform that uses it
-				 * is Windows, and this USB code only works
-				 * under FreeBSD. But hey, it doesn't cost
-				 * anything, and it makes things
-				 * consistent.
-				 */
-			break;
-
-		IO_TRACE(1)
-			perror(device);
-
-		if ((errno == ENOENT) && ((flags & PCONNFL_TRANSIENT) != 0))
-			/* Just ignore this error */
-			;
-		else if (errno != ENXIO) {
-			fprintf(stderr, _("Error: Can't open \"%s\".\n"),
-				device);
-			perror("open");
-			/*  If some other error, don't bother waiting
-			 *  for the timeout to expire.
-			 */
-			break;
-		}
-		sleep(1);
-	}
+	usb_ep0 = open_usb_device(device, flags);
 
 	/*
 	 *  If we've enabled trace for I/O, then poke the USB kernel
@@ -488,9 +606,6 @@
 	 *  preparation of doing I/O for the actual hot sync operation.
 	 */
 	if (usb_ep0 < 0) {
-		fprintf(stderr, _("%s: Can't open USB device.\n"),
-			"pconn_usb_open");
-		perror("open");
 		free(u);
 		u = pconn->io_private = NULL;
 
@@ -530,18 +645,22 @@
 	IO_TRACE(1) {
 		fprintf(stderr,
   "Device information: %s vendor %04x (%s) product %04x (%s) rev %s addr %x\n",
-			device,  udi.vendorNo, SURE(udi.vendor), 
-			udi.productNo, SURE(udi.product),
-			SURE(udi.release), udi.addr);
+			device, USB_UDI_VENDOR_NO(udi), 
+			SURE(USB_UDI_VENDOR(udi)), 
+			USB_UDI_PRODUCT_NO(udi), 
+			SURE(USB_UDI_PRODUCT(udi)),
+			SURE(USB_UDI_RELEASE(udi)), 
+			USB_UDI_ADDR(udi));
 
 	}
 
-	if ((udi.vendorNo != HANDSPRING_VENDOR_ID) &&
-	    (udi.vendorNo != PALM_VENDOR_ID))
+	if ((USB_UDI_VENDOR_NO(udi) != HANDSPRING_VENDOR_ID) &&
+	    (USB_UDI_VENDOR_NO(udi) != PALM_VENDOR_ID) &&
+	    (USB_UDI_VENDOR_NO(udi) != SONY_VENDOR_ID))
 	{
 		fprintf(stderr,
 			_("%s: Warning: Unexpected USB vendor ID %#x.\n"),
-			"pconn_usb_open", udi.vendorNo);
+			"pconn_usb_open", USB_UDI_VENDOR_NO(udi));
 	}
 
 	/*
@@ -573,14 +692,14 @@
 	 *  on future hardware platforms.
 	 */
 	bzero((void *) &ur, sizeof(ur));
-	ur.request.bmRequestType = UT_READ_VENDOR_ENDPOINT;
-	ur.request.bRequest = usbRequestVendorGetConnectionInfo;
-	USETW(ur.request.wValue, 0);
-	USETW(ur.request.wIndex, 0);
-	USETW(ur.request.wLength, 18);
-	ur.data = (void *) &ci;
-	ur.flags = USBD_SHORT_XFER_OK;
-	ur.actlen = 0;
+	USB_UCR_REQUEST(ur).bmRequestType = UT_READ_VENDOR_ENDPOINT;
+	USB_UCR_REQUEST(ur).bRequest = usbRequestVendorGetConnectionInfo;
+	USETW(USB_UCR_REQUEST(ur).wValue, 0);
+	USETW(USB_UCR_REQUEST(ur).wIndex, 0);
+	USETW(USB_UCR_REQUEST(ur).wLength, 18);
+	USB_UCR_DATA(ur) = (void *) &ci;
+	USB_UCR_FLAGS(ur) = USBD_SHORT_XFER_OK;
+	USB_UCR_ACTLEN(ur) = 0;
 	bzero((void *)&ci, sizeof(ci));
 	if (ioctl(usb_ep0, USB_DO_REQUEST, &ur) < 0) {
 		perror(_("ioctl(USB_DO_REQUEST) usbRequestVendorGetConnectionInfo failed"));
@@ -634,34 +753,37 @@
 		return -1;	  
 	}
 
-	bzero((void *) &ur, sizeof(ur));
-	ur.request.bmRequestType = UT_READ_VENDOR_ENDPOINT;
-	ur.request.bRequest = usbRequestVendorGetBytesAvailable;
-	USETW(ur.request.wValue, 0);
-	USETW(ur.request.wIndex, 5);
-	USETW(ur.request.wLength, 2);
-	ur.data = &usbresponse[0];
-	ur.flags = USBD_SHORT_XFER_OK;
-	ur.actlen = 0;
+	if (USB_UDI_VENDOR_NO(udi) != SONY_VENDOR_ID)
+	{
+		bzero((void *) &ur, sizeof(ur));
+		USB_UCR_REQUEST(ur).bmRequestType = UT_READ_VENDOR_ENDPOINT;
+		USB_UCR_REQUEST(ur).bRequest = usbRequestVendorGetBytesAvailable;
+		USETW(USB_UCR_REQUEST(ur).wValue, 0);
+		USETW(USB_UCR_REQUEST(ur).wIndex, 5);
+		USETW(USB_UCR_REQUEST(ur).wLength, 2);
+		USB_UCR_DATA(ur) = &usbresponse[0];
+		USB_UCR_FLAGS(ur) = USBD_SHORT_XFER_OK;
+		USB_UCR_ACTLEN(ur) = 0;
 
-	if (ioctl(usb_ep0, USB_DO_REQUEST, &ur) < 0) {
-		perror(_("ioctl(USB_DO_REQUEST) usbRequestVendorGetBytesAvailable failed"));
-	}
+		if (ioctl(usb_ep0, USB_DO_REQUEST, &ur) < 0) {
+			perror(_("ioctl(USB_DO_REQUEST) usbRequestVendorGetBytesAvailable failed"));
+		}
 
-	IO_TRACE(2) {
-		fprintf(stderr, "first setup 0x1 returns %d bytes: ",
-			ur.actlen);
-		for (i = 0; i < ur.actlen; i++) {
-		  fprintf(stderr, " 0x%02x", usbresponse[i]);
+		IO_TRACE(2) {
+			fprintf(stderr, "first setup 0x1 returns %d bytes: ",
+				USB_UCR_ACTLEN(ur));
+			for (i = 0; i < USB_UCR_ACTLEN(ur); i++) {
+			  fprintf(stderr, " 0x%02x", usbresponse[i]);
+			}
+			fprintf(stderr, "\n");
 		}
-		fprintf(stderr, "\n");
-	}
 
-	if (UGETW(usbresponse) != 1) {
-		fprintf(stderr,
-			_("%s: unexpected response %d to "
-			  "GetBytesAvailable.\n"),
-			"PConnection_usb", UGETW(usbresponse));
+		if (UGETW(usbresponse) != 1) {
+			fprintf(stderr,
+				_("%s: unexpected response %d to "
+				  "GetBytesAvailable.\n"),
+				"PConnection_usb", UGETW(usbresponse));
+		}
 	}
 
 
Index: src/conduit.c
===================================================================
RCS file: /var/lib/cvs/coldsync/src/conduit.c,v
retrieving revision 2.50
diff -u -r2.50 conduit.c
--- src/conduit.c	2 Apr 2002 15:29:49 -0000	2.50
+++ src/conduit.c	13 Apr 2002 06:42:40 -0000
@@ -2190,7 +2190,7 @@
 			"conduit \"%s\",\n"
 			"\tcreator: [%c%c%c%c] (0x%08lx) / "
 			"type: [%c%c%c%c] (0x%08lx)\n"
-			"\tflags: 0x%02lx\n",
+			"\tflags: 0x%02x\n",
 
 			cond->path,
 



-- 
This message was sent through the coldsync-hackers mailing list.  To remove
yourself from this mailing list, send a message to majordomo@thedotin.net
with the words "unsubscribe coldsync-hackers" in the message body.  For more
information on Coldsync, send mail to coldsync-hackers-owner@thedotin.net.