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

Re: [coldsync-hackers] Re: Palm m125 against FreeBSD, anyone?



You might be having the same problem I was having, because I think that
sometime recently FreeBSD changed the USB stuff to require that a
USB_DISCOVER be sent on the USB bus before you can connect to the ugen
device.

I don't have a Palm m125 (I have Sony Clie), but I was definitely having a
problem where it was just hanging trying to detect the device before it even
got to the protocol differences. Anyway, I have a patch for this that uses a
different way to connect to the usb bus and ugen device. This patch is
against the current CVS. You might want to give it a shot.

If this patch doesn't work, let me know. I can try a simpler version that
just sends the USB_DISCOVER. (This version uses poll to detect the device
instead of repeatedly trying to open it and has some other fixes that are
specific to the Clie).

You'll want something like the following in your .coldsyncrc:

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

Index: config.h.in
===================================================================
RCS file: /var/lib/cvs/coldsync/config.h.in,v
retrieving revision 1.42
diff -u -r1.42 config.h.in
--- config.h.in	24 Apr 2002 17:00:17 -0000	1.42
+++ config.h.in	8 May 2002 23:02:11 -0000
@@ -29,7 +29,9 @@
 #undef pid_t
 
 /* Define to `int' if <signal.h> doesn't define return value for signal() */
-#define RETSIGTYPE int
+#ifndef RETSIGTYPE
+#define RETSIGTYPE %%RETSIGTYPE%%
+#endif /* !RETSIGTYPE */
 
 /* Define to `unsigned' if <sys/types.h> doesn't define.  */
 #undef size_t
Index: configure.in
===================================================================
RCS file: /var/lib/cvs/coldsync/configure.in,v
retrieving revision 1.147
diff -u -r1.147 configure.in
--- configure.in	2 May 2002 08:13:59 -0000	1.147
+++ configure.in	8 May 2002 23:02:11 -0000
@@ -385,6 +385,8 @@
 	AC_DEFINE(HAVE_SOCKADDR6)
 fi
 
+AC_SEARCH_LIBS(getopt_long, gnugetopt)
+
 ## Checks for library functions.
 AC_CHECK_FUNCS(access \
 	fpurge \
Index: libpconn/PConnection_usb.c
===================================================================
RCS file: /var/lib/cvs/coldsync/libpconn/PConnection_usb.c,v
retrieving revision 1.35
diff -u -r1.35 PConnection_usb.c
--- libpconn/PConnection_usb.c	14 Apr 2002 05:08:32 -0000	1.35
+++ libpconn/PConnection_usb.c	8 May 2002 23:02:12 -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. */
@@ -67,15 +68,14 @@
 #  define UCR(field)	field
 #endif	/* WITH_UDI_PREFIX */
 
+#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;
 };
 
-
 /*
  *  Description of the Handspring Visor vendor specific USB
  *  commands.
@@ -207,8 +207,9 @@
 			}
 
 			u->iobufp = u->iobuf;
-			u->iobuflen = read(p->fd, u->iobufp, sizeof(u->iobuf));
+			u->iobuflen = read(p->fd, u->iobufp, (len > 1024) ? 1024: len); 
 			if (u->iobuflen < 0) {
+				fprintf(stderr, "Error: %s\n", strerror(errno));
 				perror("usb read");
 				return u->iobuflen;
 			}
@@ -282,6 +283,7 @@
 	return 0;
 }
 
+
 static int
 usb_close(PConnection *p)
 {	
@@ -357,6 +359,81 @@
 }
 
 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;
+}
+
+int
 pconn_usb_open(PConnection *pconn,
 	       const char *device,
 	       const pconn_proto_t protocol,
@@ -462,34 +539,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
@@ -503,7 +553,6 @@
 		i = 0;
 	(void) ioctl(usb_ep0, USB_SETDEBUG, &i);
 
-
 	/*
 	 *  Open the control endpoint of the USB device.  We'll use this
 	 *  to figure out if the device in question is the one we are
@@ -511,9 +560,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;
 
@@ -560,7 +606,8 @@
 	}
 
 	if ((udi.UDI(vendorNo) != HANDSPRING_VENDOR_ID) &&
-	    (udi.UDI(vendorNo) != PALM_VENDOR_ID))
+	    (udi.UDI(vendorNo) != PALM_VENDOR_ID) &&
+	    (udi.UDI(vendorNo) != SONY_VENDOR_ID))
 	{
 		fprintf(stderr,
 			_("%s: Warning: Unexpected USB vendor ID %#x.\n"),
@@ -657,34 +704,36 @@
 		return -1;	  
 	}
 
-	bzero((void *) &ur, sizeof(ur));
-	ur.UCR(request).bmRequestType = UT_READ_VENDOR_ENDPOINT;
-	ur.UCR(request).bRequest = usbRequestVendorGetBytesAvailable;
-	USETW(ur.UCR(request).wValue, 0);
-	USETW(ur.UCR(request).wIndex, 5);
-	USETW(ur.UCR(request).wLength, 2);
-	ur.UCR(data) = &usbresponse[0];
-	ur.UCR(flags) = USBD_SHORT_XFER_OK;
-	ur.UCR(actlen) = 0;
+	if (udi.UDI(vendorNo) != SONY_VENDOR_ID)
+	{
+		bzero((void *) &ur, sizeof(ur));
+		ur.UCR(request).bmRequestType = UT_READ_VENDOR_ENDPOINT;
+		ur.UCR(request).bRequest = usbRequestVendorGetBytesAvailable;
+		USETW(ur.UCR(request).wValue, 0);
+		USETW(ur.UCR(request).wIndex, 5);
+		USETW(ur.UCR(request).wLength, 2);
+		ur.UCR(data) = &usbresponse[0];
+		ur.UCR(flags) = USBD_SHORT_XFER_OK;
+		ur.UCR(actlen) = 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.UCR(actlen));
-		for (i = 0; i < ur.UCR(actlen); i++) {
-		  fprintf(stderr, " 0x%02x", usbresponse[i]);
+		IO_TRACE(2) {
+			fprintf(stderr, "first setup 0x1 returns %d bytes: ",
+				ur.UCR(actlen));
+			for (i = 0; i < ur.UCR(actlen); i++) {
+			  fprintf(stderr, " 0x%02x", usbresponse[i]);
+			}
 		}
-		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));
+		}
 	}