diff -uNr -X patchignore.txt openobex/apps/ChangeLog openobex-usb/apps/ChangeLog
--- openobex/apps/ChangeLog	2002-11-15 11:49:12.000000000 +0200
+++ openobex-usb/apps/ChangeLog	2005-12-03 12:55:40.000000000 +0200
@@ -1,3 +1,7 @@
+2005-08-30  Alex Kanavin  <ak@sensi.org>
+
+	* Add client-side USB support and interface discovery
+
 2002-11-15  Marcel Holtmann  <marcel@holtmann.org>
 
 	* Add Bluetooth server support
diff -uNr -X patchignore.txt openobex/apps/src/obex_test.c openobex-usb/apps/src/obex_test.c
--- openobex/apps/src/obex_test.c	2002-11-15 23:18:29.000000000 +0200
+++ openobex-usb/apps/src/obex_test.c	2005-12-18 23:08:22.000000000 +0200
@@ -155,13 +155,15 @@
 {
 	char cmd[10];
 	int end = 0;
-	int cobex = FALSE, tcpobex = FALSE, btobex = FALSE, r320 = FALSE;
+	int cobex = FALSE, tcpobex = FALSE, btobex = FALSE, r320 = FALSE, usbobex = FALSE;
 	obex_t *handle;
 #ifdef HAVE_BLUETOOTH
 	bdaddr_t bdaddr;
 	uint8_t channel;
 #endif
 
+	obex_interface_t *obex_intf;
+
 	struct context global_context = {0,};
 
 #ifndef _WIN32
@@ -181,7 +183,8 @@
 		tcpobex = TRUE;
 	if( (argc >= 2) && (strcmp(argv[1], "-b") == 0 ) )
 		btobex = TRUE;
-
+	if( (argc >= 2) && (strcmp(argv[1], "-u") == 0 ) )
+		usbobex = TRUE;
 
 	if(cobex)	{
 #ifndef _WIN32
@@ -262,6 +265,46 @@
 		printf("Not implemented in Win32 yet.\n");
 #endif	// _WIN32
 	}
+	else if(usbobex) {
+		int i, interfaces_number, intf_num;
+		switch (argc) {
+		case 2:
+			printf("Using USB transport, querying available interfaces\n");
+			if(! (handle = OBEX_Init(OBEX_TRANS_USB, obex_event, 0)))      {
+				perror( "OBEX_Init failed");
+				exit(0);
+			}
+			interfaces_number = OBEX_FindInterfaces(handle, &obex_intf);
+			for (i=0; i < interfaces_number; i++)
+				printf("Interface %d: %s %s %s\n", i, 
+					obex_intf[i].usb.manufacturer, 
+					obex_intf[i].usb.product, 
+					obex_intf[i].usb.control_interface);
+			printf("Use '%s -u interface_number' to run interactive OBEX test client\n", argv[0]);
+			OBEX_Cleanup(handle);
+			exit(0);
+			break;
+		case 3:
+			intf_num = atoi(argv[2]);
+			printf("Using USB transport \n");
+			if(! (handle = OBEX_Init(OBEX_TRANS_USB, obex_event, 0)))      {
+				perror( "OBEX_Init failed");
+				exit(0);
+			}
+
+			interfaces_number = OBEX_FindInterfaces(handle, &obex_intf);
+			if (intf_num >= interfaces_number) {
+				printf( "Invalid interface number\n");
+				exit(0);
+			}
+			obex_intf += intf_num;	
+
+			break;
+		default:
+			printf("Wrong number of arguments\n");
+			exit(0);
+		}
+	}
 	else	{
 		printf("Using IrDA transport\n");
 		if(! (handle = OBEX_Init(OBEX_TRANS_IRDA, obex_event, 0)))	{
@@ -321,6 +364,12 @@
 					printf("Transport not found! (Bluetooth)\n");
 #endif
 				}
+				if (usbobex) {
+					if (OBEX_InterfaceConnect(handle, obex_intf) < 0) {
+						printf("Transport connect error! (USB)\n");
+						break;
+					}
+				}	
 				else {
 					if(IrOBEX_TransportConnect(handle, IR_SERVICE) < 0) {
 						printf("Transport connect error! (IrDA)\n");
diff -uNr -X patchignore.txt openobex/lib/ChangeLog openobex-usb/lib/ChangeLog
--- openobex/lib/ChangeLog	2005-12-03 12:51:50.000000000 +0200
+++ openobex-usb/lib/ChangeLog	2005-12-18 22:54:51.000000000 +0200
@@ -1,3 +1,7 @@
+2005-12-18  Alex Kanavin       <ak@sensi.org>
+
+	* Support for USB transport layer and USB interface discovery
+
 2005-12-02  Johan Hedberg  <johan.hedberg@nokia.com>
 
 	* Add OBEX_SuspendRequest() and OBEX_ResumeRequest() functions for
diff -uNr -X patchignore.txt openobex/lib/acinclude.m4 openobex-usb/lib/acinclude.m4
--- openobex/lib/acinclude.m4	2005-11-15 22:55:03.000000000 +0200
+++ openobex-usb/lib/acinclude.m4	2005-12-18 23:08:59.000000000 +0200
@@ -47,3 +47,30 @@
 	fi
 fi
 ])
+
+dnl
+dnl USB_HOOK (script-if-usb-found, failflag)
+dnl
+dnl if failflag is "failure" it aborts if obex is not found.
+dnl
+
+AC_DEFUN([USB_HOOK],[
+	AC_CACHE_CHECK([for USB support],am_cv_usb_found,[
+
+		AC_TRY_COMPILE([#include <usb.h>],
+		[struct usb_dev_handle *dev;],
+		am_cv_usb_found=yes,
+		am_cv_usb_found=no)])
+
+		if test $am_cv_usb_found = yes; then
+			AC_DEFINE(HAVE_USB,1,[Define if system supports USB])
+			USB_LIBS="-lusb"
+		fi
+		AC_SUBST(USB_LIBS)
+	])
+
+])
+
+AC_DEFUN([USB_CHECK], [
+	USB_HOOK([],failure)
+])
diff -uNr -X patchignore.txt openobex/lib/configure.in openobex-usb/lib/configure.in
--- openobex/lib/configure.in	2005-11-15 22:55:03.000000000 +0200
+++ openobex-usb/lib/configure.in	2005-12-03 12:55:40.000000000 +0200
@@ -38,6 +38,7 @@
 
 IRDA_CHECK
 BLUETOOTH_CHECK
+USB_CHECK
 
 dnl Configure debug facilities
 AC_ARG_WITH(debug,[  --with-debug=level      Debug level],
diff -uNr -X patchignore.txt openobex/lib/src/Makefile.am openobex-usb/lib/src/Makefile.am
--- openobex/lib/src/Makefile.am	2002-10-28 23:51:18.000000000 +0200
+++ openobex-usb/lib/src/Makefile.am	2005-12-03 12:55:40.000000000 +0200
@@ -22,7 +22,8 @@
 	inobex.c inobex.h \
 	btobex.c btobex.h \
 	netbuf.c netbuf.h \
-	irda.h irda_wrap.h
+	irda.h irda_wrap.h \
+	usbobex.c usbobex.h
 
 libopenobex_la_LDFLAGS = \
 	-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
@@ -32,4 +33,6 @@
 
 INCLUDES = -I$(top_srcdir)/src
 
+libopenobex_la_LIBADD = @USB_LIBS@
+
 EXTRA_DIST = obex.sym obex.def makefile.msc win32compat.c windeps.dep
diff -uNr -X patchignore.txt openobex/lib/src/obex.c openobex-usb/lib/src/obex.c
--- openobex/lib/src/obex.c	2005-12-03 12:51:50.000000000 +0200
+++ openobex-usb/lib/src/obex.c	2005-12-18 23:12:22.000000000 +0200
@@ -55,6 +55,9 @@
 #ifdef HAVE_IRDA
 #include "irobex.h"
 #endif
+#ifdef HAVE_USB
+#include "usbobex.h"
+#endif
 #ifdef HAVE_BLUETOOTH
 #include "btobex.h"
 #else
@@ -69,6 +72,7 @@
  *             %OBEX_TRANS_INET : Use regular TCP/IP socket
  *             %OBEX_TRANS_CUSTOM : Use user provided transport
  *             %OBEX_TRANS_BLUETOOTH: Use regular Bluetooth RFCOMM socket (need the BlueZ stack)
+ *             %OBEX_TRANS_USB: Use USB transport (libusb needed)
  *             If you use %OBEX_TRANS_CUSTOM you must register your own
  *             transport with OBEX_RegisterCTransport()
  * @eventcb: Function pointer to your event callback.
@@ -121,25 +125,32 @@
 	/* Init transport */
 	self->trans.type = transport;
 	self->trans.connected = FALSE;
+	
+	/* Safe values.
+	 * Both self->mtu_rx and self->mtu_tx_max can be increased by app
+	 * self->mtu_tx will be whatever the other end sneds us - Jean II */
+	/* Set MTU to the maximum, if using USB transport - Alex Kanavin */
+	if (transport == OBEX_TRANS_USB) {
+		self->mtu_rx = OBEX_MAXIMUM_MTU;
+		self->mtu_tx = OBEX_MINIMUM_MTU;
+		self->mtu_tx_max = OBEX_MAXIMUM_MTU;
+	} else {
+		self->mtu_rx = OBEX_DEFAULT_MTU;
+		self->mtu_tx = OBEX_MINIMUM_MTU;
+		self->mtu_tx_max = OBEX_DEFAULT_MTU;
+	}
 
 	/* Allocate message buffers */
 	/* It's safe to allocate them smaller than OBEX_MAXIMUM_MTU
 	 * because netbuf will realloc data as needed. - Jean II */
-	self->rx_msg = g_netbuf_new(OBEX_DEFAULT_MTU);
+	self->rx_msg = g_netbuf_new(self->mtu_rx);
 	if (self->rx_msg == NULL)
 		goto out_err;
 
-	self->tx_msg = g_netbuf_new(OBEX_DEFAULT_MTU);
+	self->tx_msg = g_netbuf_new(self->mtu_tx_max);
 	if (self->tx_msg == NULL)
 		goto out_err;
 
-	/* Safe values.
-	 * Both self->mtu_rx and self->mtu_tx_max can be increased by app
-	 * self->mtu_tx will be whatever the other end sneds us - Jean II */
-	self->mtu_rx = OBEX_DEFAULT_MTU;
-	self->mtu_tx = OBEX_MINIMUM_MTU;
-	self->mtu_tx_max = OBEX_DEFAULT_MTU;
-
 #ifndef _WIN32
 	/* Ignore SIGPIPE. Otherwise send() will raise it and the app will quit */
 	signal(SIGPIPE, SIG_IGN);
@@ -192,7 +203,8 @@
 	
 	if (self->rx_msg)
 		g_netbuf_free(self->rx_msg);
-	
+
+	OBEX_FreeInterfaces(self);
 	free(self);
 }
 
@@ -1077,3 +1089,81 @@
 	return obex_transport_connect_request(self);
 }
 
+/**
+ *  OBEX_InterfaceConnect - Connect USB interface
+ *  @self: OBEX handle
+ *  @interface: USB interface to connect to
+ *
+ *  An easier connect function to connect to a discovered interface (currently
+ *  USB OBEX only). 
+ */
+int OBEX_InterfaceConnect(obex_t *self, obex_interface_t *interface)
+{
+	DEBUG(4, "\n");
+
+	obex_return_val_if_fail(self != NULL, -1);
+
+	if (self->object) {
+		DEBUG(1, "We are busy.\n");
+		return -EBUSY;
+	}
+
+	obex_return_val_if_fail(interface != NULL, -1);
+	switch (self->trans.type) {
+	case OBEX_TRANS_USB:
+		obex_return_val_if_fail(interface->usb.interface != NULL, -1);
+#ifdef HAVE_USB
+		usbobex_prepare_connect(self, interface->usb.interface);
+		return obex_transport_connect_request(self);
+#else
+		return -ESOCKTNOSUPPORT;
+#endif /* HAVE_USB */
+	default:
+		return -ESOCKTNOSUPPORT;
+	}
+}
+
+/**
+ *  OBEX_FindInterfaces - Get a list of OBEX interfaces on the system
+ *  @self: OBEX handle
+ *  @interfaces: A list of OBEX interfaces
+ *
+ *  Gets a list of OBEX interfaces, or NULL if there are none.
+ */
+int OBEX_FindInterfaces(obex_t *self, obex_interface_t **interfaces)
+{
+	DEBUG(4, "\n");
+	OBEX_FreeInterfaces(self);
+	switch (self->trans.type) {
+	case OBEX_TRANS_USB:
+#ifdef HAVE_USB
+		self->interfaces_number = usbobex_find_interfaces(&self->interfaces);
+#endif
+		break;
+	default:
+		break;
+	}
+	*interfaces = self->interfaces;
+	return self->interfaces_number;
+}
+
+/**
+ *  OBEX_FreeInterfaces - free memory allocated to OBEX interface structures
+ *  @self: OBEX handle
+ *
+ *  Frees memory allocated to OBEX interface structures after it has been 
+ *  allocated by OBEX_FindInterfaces.
+ */
+void OBEX_FreeInterfaces(obex_t *self)
+{
+	switch (self->trans.type) {
+	case OBEX_TRANS_USB:
+#ifdef HAVE_USB
+		usbobex_free_interfaces(self->interfaces_number, self->interfaces);
+#endif
+		break;
+	default:
+		break;
+	}
+	self->interfaces_number = 0;
+}
diff -uNr -X patchignore.txt openobex/lib/src/obex.def openobex-usb/lib/src/obex.def
--- openobex/lib/src/obex.def	2005-12-03 12:51:50.000000000 +0200
+++ openobex-usb/lib/src/obex.def	2005-12-18 22:51:57.000000000 +0200
@@ -40,3 +40,6 @@
 BtOBEX_ServerRegister
 BtOBEX_TransportConnect
 FdOBEX_TransportSetup
+OBEX_InterfaceConnect
+OBEX_FindInterfaces
+OBEX_FreeInterfaces
diff -uNr -X patchignore.txt openobex/lib/src/obex.h openobex-usb/lib/src/obex.h
--- openobex/lib/src/obex.h	2005-12-03 12:51:50.000000000 +0200
+++ openobex-usb/lib/src/obex.h	2005-12-18 23:12:41.000000000 +0200
@@ -136,4 +136,10 @@
  */
 int FdOBEX_TransportSetup(obex_t *self, int rfd, int wfd, int mtu);
 
+/*  
+ * OBEX interface discovery API 
+ */
+ int OBEX_FindInterfaces(obex_t *self, obex_interface_t **interfaces);
+ int OBEX_InterfaceConnect(obex_t *self, obex_interface_t *interface);
+ void OBEX_FreeInterfaces(obex_t *self);
 #endif
diff -uNr -X patchignore.txt openobex/lib/src/obex.sym openobex-usb/lib/src/obex.sym
--- openobex/lib/src/obex.sym	2005-12-03 12:51:50.000000000 +0200
+++ openobex-usb/lib/src/obex.sym	2005-12-18 22:52:26.000000000 +0200
@@ -39,3 +39,6 @@
 BtOBEX_ServerRegister
 BtOBEX_TransportConnect
 FdOBEX_TransportSetup
+OBEX_InterfaceConnect
+OBEX_FindInterfaces
+OBEX_FreeInterfaces
diff -uNr -X patchignore.txt openobex/lib/src/obex_const.h openobex-usb/lib/src/obex_const.h
--- openobex/lib/src/obex_const.h	2005-11-15 22:55:03.000000000 +0200
+++ openobex-usb/lib/src/obex_const.h	2005-12-18 23:14:15.000000000 +0200
@@ -47,6 +47,33 @@
 	void * customdata;
 } obex_ctrans_t;
 
+/* USB-specific OBEX interface information */
+typedef struct {
+	/* Manufacturer, e.g. Nokia */
+	char *manufacturer;
+	/* Product, e.g. Nokia 6680 */
+	char *product;
+	/* Product serial number */
+	char *serial;
+	/* USB device configuration description */
+	char *configuration;
+	/* Control interface description */
+	char *control_interface;
+	/* Idle data interface description, typically empty */
+	char *data_interface_idle;
+	/* Active data interface description, typically empty */
+	char *data_interface_active;
+	/* Internal information for the transport layer in the library */
+	struct obex_usb_intf_transport_t *interface;
+} obex_usb_intf_t;
+
+/* Generic OBEX interface information */
+typedef union {
+	/* USB-specific OBEX interface information */
+	obex_usb_intf_t usb;
+//	obex_bluetooth_intf_t bt; // to be added
+} obex_interface_t;
+
 #define	OBEX_CLIENT		0
 #define	OBEX_SERVER		1
 
@@ -81,6 +108,7 @@
 #define OBEX_TRANS_CUSTOM	3
 #define OBEX_TRANS_BLUETOOTH	4
 #define OBEX_TRANS_FD		5
+#define OBEX_TRANS_USB		6
 
 /* Standard headers */
 #define OBEX_HDR_COUNT		0xc0 /* Number of objects (used by connect) */
diff -uNr -X patchignore.txt openobex/lib/src/obex_main.h openobex-usb/lib/src/obex_main.h
--- openobex/lib/src/obex_main.h	2002-11-22 21:06:11.000000000 +0200
+++ openobex-usb/lib/src/obex_main.h	2005-12-18 23:17:20.000000000 +0200
@@ -139,6 +139,10 @@
 
 	obex_transport_t trans;		/* Transport being used */
 	obex_ctrans_t ctrans;
+
+	obex_interface_t *interfaces;	/* Array of discovered interfaces */
+	int interfaces_number;		/* Number of discovered interfaces */
+
 	void * userdata;		/* For user */
 };
 
diff -uNr -X patchignore.txt openobex/lib/src/obex_transport.c openobex-usb/lib/src/obex_transport.c
--- openobex/lib/src/obex_transport.c	2002-11-22 21:06:12.000000000 +0200
+++ openobex-usb/lib/src/obex_transport.c	2005-12-03 13:42:35.000000000 +0200
@@ -43,6 +43,9 @@
 #ifdef HAVE_BLUETOOTH
 #include "btobex.h"
 #endif /*HAVE_BLUETOOTH*/
+#ifdef HAVE_USB 
+#include "usbobex.h" 
+#endif /*HAVE_USB*/ 
 
 #include "obex_transport.h"
 
@@ -64,6 +67,9 @@
 			ret = -1;
 		}
 	}
+	else if (self->trans.type == OBEX_TRANS_USB) {
+		ret = obex_data_indication(self, NULL, 0);
+	}
 	else {
 		struct timeval time;
 		fd_set fdset;
@@ -205,7 +211,11 @@
 		if (self->fd >= 0 && self->writefd >= 0)
 			ret = 0;
 		break;
-
+#ifdef HAVE_USB 
+	case OBEX_TRANS_USB:
+		ret = usbobex_connect_request(self);
+		break;
+#endif /*HAVE_USB*/ 
 	default:
 		DEBUG(4, "Transport not implemented!\n");
 		break;
@@ -250,6 +260,11 @@
 		/* no real disconnect on a file */
 		self->fd = self->writefd = -1;
 		break;
+#ifdef HAVE_USB 
+	case OBEX_TRANS_USB:
+		usbobex_disconnect_request(self);
+		break;
+#endif /*HAVE_USB*/ 
 	default:
 		DEBUG(4, "Transport not implemented!\n");
 		break;
@@ -289,7 +304,8 @@
 		break;
 #endif /*HAVE_BLUETOOTH*/
 	case OBEX_TRANS_FD:
-		/* no real listen on the file */
+	case OBEX_TRANS_USB:
+		/* no real listen on the file or USB */
 		ret = 0;
 		break;
 	default:
@@ -330,7 +346,8 @@
 		break;
 #endif /*HAVE_BLUETOOTH*/
 	case OBEX_TRANS_FD:
-		/* no real server on a file */;
+	case OBEX_TRANS_USB:
+		/* no real server on a file or USB */;
 		break;
 	default:
 		DEBUG(4, "Transport not implemented!\n");
@@ -389,6 +406,16 @@
 	case OBEX_TRANS_FD:
 		actual = do_write(self->writefd, msg, self->trans.mtu);
 		break;
+#ifdef HAVE_USB 
+	case OBEX_TRANS_USB:
+		if (self->trans.connected != TRUE)
+			break;
+		DEBUG(4, "Endpoint %d\n", self->trans.self.usb.interface->data_endpoint_write);
+		actual = usb_bulk_write(self->trans.self.usb.dev_data, 
+		    self->trans.self.usb.data_endpoint_write,
+		    msg->data, msg->len, USB_OBEX_TIMEOUT);
+		break;
+#endif /*HAVE_USB*/ 
 	case OBEX_TRANS_CUSTOM:
 		DEBUG(4, "Custom write\n");
 		if(self->ctrans.write)
@@ -427,6 +454,16 @@
 	case OBEX_TRANS_FD:
 		actual = read(self->fd, msg->tail, max);
 		break;
+#ifdef HAVE_USB 
+	case OBEX_TRANS_USB:
+		if (self->trans.connected != TRUE)
+			break;
+		DEBUG(4, "Endpoint %d\n", self->trans.self.usb.interface->data_endpoint_read);
+		actual = usb_bulk_read(self->trans.self.usb.dev_data, 
+		    self->trans.self.usb.data_endpoint_read,
+		    msg->tail, self->mtu_rx, USB_OBEX_TIMEOUT);
+		break;
+#endif /*HAVE_USB*/ 
 	case OBEX_TRANS_CUSTOM:
 		if(buflen > max) {
 			memcpy(msg->tail, buf, max);
diff -uNr -X patchignore.txt openobex/lib/src/obex_transport.h openobex-usb/lib/src/obex_transport.h
--- openobex/lib/src/obex_transport.h	2004-03-05 11:48:49.000000000 +0200
+++ openobex-usb/lib/src/obex_transport.h	2005-12-18 22:36:44.000000000 +0200
@@ -43,6 +43,9 @@
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/rfcomm.h>
 #endif /*HAVE_BLUETOOTH*/
+#ifdef HAVE_USB
+#include "usbobex.h"
+#endif /*HAVE_USB*/
 
 #include "obex_main.h"
 
@@ -54,6 +57,9 @@
 #ifdef HAVE_BLUETOOTH
 	struct sockaddr_rc   rfcomm;
 #endif /*HAVE_BLUETOOTH*/
+#ifdef HAVE_USB
+	struct obex_usb_intf_transport_t usb;
+#endif /*HAVE_USB*/
 } saddr_t;
 
 typedef struct obex_transport {
diff -uNr -X patchignore.txt openobex/lib/src/usbobex.c openobex-usb/lib/src/usbobex.c
--- openobex/lib/src/usbobex.c	1970-01-01 02:00:00.000000000 +0200
+++ openobex-usb/lib/src/usbobex.c	2005-12-18 23:24:34.000000000 +0200
@@ -0,0 +1,414 @@
+/*************************************<********************************
+ *                
+ * Filename:      usbobex.c
+ * Version:       0.1
+ * Description:   USB OBEX, USB transport for OBEX
+ * Status:        Experimental.
+ * Author:        Alex Kanavin <ak@sensi.org>
+ * 
+ *     Copyright (c) 2005 Alex Kanavin, All Rights Reserved.
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2 of the License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA  02111-1307  USA
+ *     
+ ********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_USB
+
+/* Linux case */
+
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>		/* perror */
+#include <errno.h>		/* errno and EADDRNOTAVAIL */
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include <usb.h>
+
+#include <obex_main.h>
+#include <usbobex.h>
+
+/*
+ * Function usbobex_prepare_connect (self, interface)
+ *
+ *    Prepare for USB OBEX connect
+ *
+ */
+void usbobex_prepare_connect(obex_t *self, struct obex_usb_intf_transport_t *intf)
+{
+#ifndef _WIN32
+	self->trans.self.usb = *intf;
+#endif /* _WIN32 */
+}
+
+/*
+ * Helper function to usbobex_find_interfaces 
+ */
+static void find_eps(struct obex_usb_intf_transport_t *intf, struct usb_interface_descriptor data_intf, int *found_active, int *found_idle)
+{
+	struct usb_endpoint_descriptor *ep0, *ep1;
+
+	if (data_intf.bNumEndpoints == 2) {
+		ep0 = data_intf.endpoint;
+		ep1 = data_intf.endpoint + 1;
+		if ((ep0->bEndpointAddress & USB_ENDPOINT_IN) && 
+		    ((ep0->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK) && 
+		    !(ep1->bEndpointAddress & USB_ENDPOINT_IN) && 
+		    ((ep1->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK)) {
+			*found_active = 1;
+			intf->data_active_setting = data_intf.bAlternateSetting;
+			intf->data_interface_active_description = data_intf.iInterface;
+			intf->data_endpoint_read = ep0->bEndpointAddress;
+			intf->data_endpoint_write = ep1->bEndpointAddress;
+		}
+		if (!(ep0->bEndpointAddress & USB_ENDPOINT_IN) && 
+		    ((ep0->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK) && 
+		    (ep1->bEndpointAddress & USB_ENDPOINT_IN) && 
+		    ((ep1->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK)) {
+			*found_active = 1;
+			intf->data_active_setting = data_intf.bAlternateSetting;
+			intf->data_interface_active_description = data_intf.iInterface;
+			intf->data_endpoint_read = ep1->bEndpointAddress;
+			intf->data_endpoint_write = ep0->bEndpointAddress;
+		}
+	}
+	if (data_intf.bNumEndpoints == 0) {
+		*found_idle = 1;
+		intf->data_idle_setting = data_intf.bAlternateSetting;
+		intf->data_interface_idle_description = data_intf.iInterface;
+	}
+}
+
+/*
+ * Helper function to usbobex_find_interfaces 
+ */
+static int find_obex_data_interface(unsigned char *buffer, int buflen, struct usb_config_descriptor config, struct obex_usb_intf_transport_t *intf)
+{
+	struct cdc_union_desc *union_header = NULL;
+	int i, a;
+	int found_active = 0;
+	int found_idle = 0;
+
+	if (!buffer) {
+		DEBUG(2,"Weird descriptor references");
+		return -EINVAL;
+	}
+	while (buflen > 0) {
+		if (buffer [1] != USB_DT_CS_INTERFACE) {
+			DEBUG(2,"skipping garbage");
+			goto next_desc;
+		}
+		switch (buffer [2]) {
+		case CDC_UNION_TYPE: /* we've found it */
+			if (union_header) {
+				DEBUG(2,"More than one union descriptor, skiping ...");
+				goto next_desc;
+			}
+			union_header = (struct cdc_union_desc *)buffer;
+			break;
+		case CDC_OBEX_TYPE: /* maybe check version */
+		case CDC_HEADER_TYPE:
+			break; /* for now we ignore it */
+		default:
+			DEBUG(2, "Ignoring extra header, type %d, length %d", buffer[2], buffer[0]);
+			break;
+		}
+next_desc:
+		buflen -= buffer[0];
+		buffer += buffer[0];
+	}
+	if (!union_header) {
+		DEBUG(2,"No union descriptor, giving up\n");
+		return -ENODEV;
+	}
+	/* Found the slave interface, now find active/idle settings and endpoints */
+	intf->data_interface = union_header->bSlaveInterface0;
+	/* Loop through all of the interfaces */
+	for (i = 0; i < config.bNumInterfaces; i++) {
+		/* Loop through all of the alternate settings */
+		for (a = 0; a < config.interface[i].num_altsetting; a++) {
+			/* Check if this interface is OBEX data interface*/
+			/* and find endpoints */
+			if (config.interface[i].altsetting[a].bInterfaceNumber == intf->data_interface) {
+				find_eps(intf, config.interface[i].altsetting[a], &found_active, &found_idle);
+			}
+		}
+	}
+	if (!found_idle) {
+		DEBUG(2,"No idle setting\n");
+		return -ENODEV;
+	}
+	if (!found_active) {
+		DEBUG(2,"No active setting\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+/*
+ * Helper function to usbobex_find_interfaces
+ */
+static int get_intf_string(struct usb_dev_handle *usb_handle, char **string, int id)
+{
+	if (id) {
+		if ((*string = malloc(USB_MAX_STRING_SIZE)) == NULL)
+			return -ENOMEM;
+		*string[0] = '\0';
+		return usb_get_string_simple(usb_handle, id, *string, USB_MAX_STRING_SIZE);
+	}
+	return 0;
+}
+
+/*
+ * Helper function to usbobex_find_interfaces 
+ */
+static struct obex_usb_intf_transport_t *check_intf(struct usb_device *dev, int c, int i, int a, struct obex_usb_intf_transport_t *current)
+{
+	struct obex_usb_intf_transport_t *next = NULL;
+
+	if ((dev->config[c].interface[i].altsetting[a].bInterfaceClass == USB_CDC_CLASS) 
+	    && (dev->config[c].interface[i].altsetting[a].bInterfaceSubClass == USB_CDC_OBEX_SUBCLASS)) { 
+		int err;
+		unsigned char *buffer = dev->config[c].interface[i].altsetting[a].extra;
+		int buflen = dev->config[c].interface[i].altsetting[a].extralen;
+
+		next = malloc(sizeof(struct obex_usb_intf_transport_t));
+		if (next == NULL)
+			return current;
+		next->device = dev;
+		next->configuration = dev->config[c].bConfigurationValue;
+		next->configuration_description = dev->config[c].iConfiguration;
+		next->control_interface = dev->config[c].interface[i].altsetting[a].bInterfaceNumber;
+		next->control_interface_description = dev->config[c].interface[i].altsetting[a].iInterface;
+		next->control_setting = dev->config[c].interface[i].altsetting[a].bAlternateSetting;
+
+		err = find_obex_data_interface(buffer, buflen, dev->config[c], next);
+		if (err)
+			free(next);
+		else {
+			if (current)
+				current->next = next;
+			next->prev = current;
+			next->next = NULL;
+			current = next;
+		}
+	}
+	return current;
+}
+
+/*
+ * Function usbobex_find_interfaces ()
+ *
+ *    Find available USBOBEX interfaces on the system
+ */
+int usbobex_find_interfaces(obex_interface_t **interfaces)
+{
+	struct usb_bus *busses;
+	struct usb_bus *bus;
+	struct usb_device *dev;
+	int c, i, a, num;
+	struct obex_usb_intf_transport_t *current = NULL;
+	struct obex_usb_intf_transport_t *tmp = NULL;
+	obex_interface_t *intf_array = NULL; 	
+	struct usb_dev_handle *usb_handle;
+	
+	usb_init();
+	usb_find_busses();
+	usb_find_devices();
+
+	busses = usb_get_busses();
+
+	for (bus = busses; bus; bus = bus->next) {
+		for (dev = bus->devices; dev; dev = dev->next) {
+			/* Loop through all of the configurations */
+			for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
+				/* Loop through all of the interfaces */
+				for (i = 0; i < dev->config[c].bNumInterfaces; i++) {
+					/* Loop through all of the alternate settings */
+					for (a = 0; a < dev->config[c].interface[i].num_altsetting; a++) {
+						/* Check if this interface is OBEX */
+						/* and find data interface */
+						current = check_intf(dev, c, i, a, current);
+					}
+				}
+			}
+		}
+	}
+	num = 0;
+	if (current) 
+		num++;
+	while (current && current->prev) {
+		current = current->prev;
+		num++;
+	}
+	intf_array = malloc(sizeof(obex_interface_t) * num);
+	if (intf_array == NULL)
+		goto cleanup_list;
+	memset(intf_array, 0, sizeof(obex_interface_t) * num);
+	num = 0;
+	while (current) {
+		intf_array[num].usb.interface = current;
+		usb_handle = usb_open(current->device);
+		get_intf_string(usb_handle, &intf_array[num].usb.manufacturer, 
+			current->device->descriptor.iManufacturer);
+		get_intf_string(usb_handle, &intf_array[num].usb.product, 
+			current->device->descriptor.iProduct);
+		get_intf_string(usb_handle, &intf_array[num].usb.serial, 
+			current->device->descriptor.iSerialNumber);
+		get_intf_string(usb_handle, &intf_array[num].usb.configuration, 
+			current->configuration_description);
+		get_intf_string(usb_handle, &intf_array[num].usb.control_interface, 
+			current->control_interface_description);
+		get_intf_string(usb_handle, &intf_array[num].usb.data_interface_idle, 
+			current->data_interface_idle_description);
+		get_intf_string(usb_handle, &intf_array[num].usb.data_interface_active, 
+			current->data_interface_active_description);
+		usb_close(usb_handle);
+		current = current->next; num++;
+	}
+	*interfaces = intf_array;
+	return num;
+
+cleanup_list:
+	while (current) {
+		tmp = current->next;
+		free(current);
+		current = tmp;
+	}
+	return 0;
+}
+
+/*
+ * Function usbobex_free_interfaces ()
+ *
+ *    Free the list of discovered USBOBEX interfaces on the system
+ */
+void usbobex_free_interfaces(int num, obex_interface_t *intf)
+{
+	int i;
+	if (intf == NULL)
+		return;
+	for (i=0; i++; i<num) {
+		free(intf[i].usb.manufacturer);
+		free(intf[i].usb.product);
+		free(intf[i].usb.serial);
+		free(intf[i].usb.configuration);
+		free(intf[i].usb.control_interface);
+		free(intf[i].usb.data_interface_idle);
+		free(intf[i].usb.data_interface_active);
+		free(intf[i].usb.interface);
+	}
+	free(intf);
+}
+
+/*
+ * Function usbobex_connect_request (self)
+ *
+ *    Open the USB connection
+ *
+ */
+int usbobex_connect_request(obex_t *self)
+{
+	int ret;
+#ifndef _WIN32
+
+	DEBUG(4, "\n");
+
+	self->trans.self.usb.dev_control = usb_open(self->trans.self.usb.device);
+	self->trans.self.usb.dev_data = usb_open(self->trans.self.usb.device);
+
+	ret = usb_set_configuration(self->trans.self.usb.dev_control, self->trans.self.usb.configuration);
+	if (ret < 0) {
+		DEBUG(4, "Can't set configuration %d", ret);
+		goto err1;
+	}
+
+	ret = usb_claim_interface(self->trans.self.usb.dev_control, self->trans.self.usb.control_interface);
+	if (ret < 0) {
+		DEBUG(4, "Can't claim control interface %d", ret);
+		goto err1;
+	}
+
+	ret = usb_set_altinterface(self->trans.self.usb.dev_control, self->trans.self.usb.control_setting);
+	if (ret < 0) {
+		DEBUG(4, "Can't set control setting %d", ret);
+		goto err2;
+	}
+
+	ret = usb_claim_interface(self->trans.self.usb.dev_data, self->trans.self.usb.data_interface);
+	if (ret < 0) {
+		DEBUG(4, "Can't claim data interface %d", ret);
+		goto err2;
+	}
+
+	ret = usb_set_altinterface(self->trans.self.usb.dev_data, self->trans.self.usb.data_active_setting);
+	if (ret < 0) {
+		DEBUG(4, "Can't set data active setting %d", ret);
+		goto err3;
+	}
+	self->trans.mtu = OBEX_MAXIMUM_MTU;
+	DEBUG(2, "transport mtu=%d\n", self->trans.mtu);
+	return 1;
+
+err3:
+	usb_release_interface(self->trans.self.usb.dev_data, self->trans.self.usb.data_interface);	
+err2:
+	usb_release_interface(self->trans.self.usb.dev_control, self->trans.self.usb.control_interface);
+err1:
+	usb_close(self->trans.self.usb.dev_data);
+	usb_close(self->trans.self.usb.dev_control);
+	return ret;
+
+#endif /* _WIN32 */
+}
+
+/*
+ * Function usbobex_link_disconnect_request (self)
+ *
+ *    Shutdown the USB link
+ *
+ */
+int usbobex_disconnect_request(obex_t *self)
+{
+	int ret;
+	if (self->trans.connected == FALSE)
+		return 0;
+#ifndef _WIN32
+	DEBUG(4, "\n");
+	ret = usb_set_altinterface(self->trans.self.usb.dev_data, self->trans.self.usb.data_idle_setting);
+	if (ret < 0)
+		DEBUG(4, "Can't set data idle setting %d", ret);
+	ret = usb_release_interface(self->trans.self.usb.dev_data, self->trans.self.usb.data_interface);
+	if (ret < 0) 
+		DEBUG(4, "Can't release data interface %d", ret);
+	ret = usb_release_interface(self->trans.self.usb.dev_control, self->trans.self.usb.control_interface);
+	if (ret < 0) 
+		DEBUG(4, "Can't release control interface %d", ret);
+	ret = usb_close(self->trans.self.usb.dev_data);
+	if (ret < 0)
+		DEBUG(4, "Can't close data interface %d", ret);
+	ret = usb_close(self->trans.self.usb.dev_control);
+	if (ret < 0)
+		DEBUG(4, "Can't close control interface %d", ret);
+#endif /* _WIN32 */
+	return ret;	
+}
+
+#endif /* HAVE_USB */
diff -uNr -X patchignore.txt openobex/lib/src/usbobex.h openobex-usb/lib/src/usbobex.h
--- openobex/lib/src/usbobex.h	1970-01-01 02:00:00.000000000 +0200
+++ openobex-usb/lib/src/usbobex.h	2005-12-18 23:18:36.000000000 +0200
@@ -0,0 +1,94 @@
+/*********************************************************************
+ *                
+ * Filename:      usbobex.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Alex Kanavin <ak@sensi.org>
+ * 
+ *     Copyright (c) 2005 Alex Kanavin, All Rights Reserved.
+ *     
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2 of the License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA  02111-1307  USA
+ *     
+ ********************************************************************/
+
+#ifndef USBOBEX_H
+#define USBOBEX_H
+
+#include "obex_const.h"
+#include "usb.h"
+
+/* Information about a USB OBEX interface present on the system */
+struct obex_usb_intf_transport_t {
+	struct obex_usb_intf_transport_t *prev, *next;	/* Next and previous interfaces in the list */
+	struct usb_device *device;		/* USB device that has the interface */
+	int configuration;			/* Device configuration */
+	int configuration_description;		/* Configuration string descriptor number */
+	int control_interface;			/* OBEX master interface */
+	int control_setting;			/* OBEX master interface setting */
+	int control_interface_description;	/* OBEX master interface string descriptor number 
+						 * If non-zero, use usb_get_string_simple() from 
+						 * libusb to retrieve human-readable description
+						 */
+	int data_interface;			/* OBEX data/slave interface */
+	int data_idle_setting;			/* OBEX data/slave idle setting */
+	int data_interface_idle_description;	/* OBEX data/slave interface string descriptor number
+						 * in idle setting */
+	int data_active_setting;		/* OBEX data/slave active setting */
+	int data_interface_active_description;	/* OBEX data/slave interface string descriptor number
+						 * in active setting */
+	int data_endpoint_read;			/* OBEX data/slave interface read endpoint */
+	int data_endpoint_write;		/* OBEX data/slave interface write endpoint */
+	usb_dev_handle *dev_control;		/* libusb handler for control interace */
+	usb_dev_handle *dev_data;		/* libusb handler for data interface */
+};
+
+/* "Union Functional Descriptor" from CDC spec 5.2.3.X
+ * used to find data/slave OBEX interface */
+struct cdc_union_desc {
+	u_int8_t      bLength;
+	u_int8_t      bDescriptorType;
+	u_int8_t      bDescriptorSubType;
+
+	u_int8_t      bMasterInterface0;
+	u_int8_t      bSlaveInterface0;
+} __attribute__ ((packed));
+
+/* CDC class and subclass types */
+#define USB_CDC_CLASS			0x02
+#define USB_CDC_OBEX_SUBCLASS		0x0b
+
+/* class and subclass specific descriptor types */
+#define CDC_HEADER_TYPE			0x00
+#define CDC_CALL_MANAGEMENT_TYPE	0x01
+#define CDC_AC_MANAGEMENT_TYPE		0x02
+#define CDC_UNION_TYPE			0x06
+#define CDC_COUNTRY_TYPE		0x07
+#define CDC_OBEX_TYPE			0x15
+
+/* Interface descriptor */
+#define USB_DT_CS_INTERFACE		0x24
+#define CDC_DATA_INTERFACE_TYPE		0x0a
+
+#define USB_MAX_STRING_SIZE		256
+#define USB_OBEX_TIMEOUT		10000 /* 10 seconds */
+
+void usbobex_prepare_connect(obex_t *self, struct obex_usb_intf_transport_t *intf);
+int usbobex_connect_request(obex_t *self);
+int usbobex_disconnect_request(obex_t *self);
+int usbobex_find_interfaces(obex_interface_t **interfaces);
+void usbobex_free_interfaces(int num, obex_interface_t *intf);
+#endif
