--- acinclude.m4 | 25 +++- configure.ac | 1 + doc/Doxyfile | 2 +- doc/Doxyfile.in | 2 +- lib/Makefile.am | 7 +- lib/obex_transport.c | 19 +++ lib/usb1obex.c | 419 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/usbobex.c | 55 +------ lib/usbobex.h | 16 ++- lib/usbutils.c | 82 ++++++++++ lib/usbutils.h | 30 ++++ 11 files changed, 599 insertions(+), 59 deletions(-) create mode 100644 lib/usb1obex.c create mode 100644 lib/usbutils.c create mode 100644 lib/usbutils.h
diff --git a/acinclude.m4 b/acinclude.m4 index 06646bf..6955907 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -188,6 +188,23 @@ AC_DEFUN([AC_PATH_USB], [ fi ]) +AC_DEFUN([AC_PATH_USB1], [ + usb1_lib_found=no + PKG_CHECK_MODULES(USB1, libusb-1.0, usb1_lib_found=yes, AC_MSG_RESULT(no)) + AC_CHECK_FILE(${prefix}/lib/pkgconfig/libusb-1.0.pc, REQUIRES="libusb1") + AC_SUBST(USB1_CFLAGS) + AC_SUBST(USB1_LIBS) + + usb1_get_device_list=no + AC_CHECK_LIB(usb-1.0, libusb_get_device_list, usb1_get_device_list=yes, AC_DEFINE(NEED_USB1_GET_DEVICE_LIST, 1, [Define to 1 if you need the libusb_get_device_list() function.])) + + if (test "$usb1_lib_found" = "yes" && test "$usb1_get_device_list" = "yes"); then + usb1_found=yes + else + usb1_found=no + fi +]) + dnl AC_DEFUN([AC_PATH_GLIB], [ dnl PKG_CHECK_MODULES(GLIB, glib-2.0 gobject-2.0 gthread-2.0, glib_found=yes, AC_MSG_RESULT(no)) dnl AC_SUBST(GLIB_CFLAGS) @@ -293,8 +310,12 @@ AC_DEFUN([AC_ARG_OPENOBEX], [ AC_DEFINE(HAVE_BLUETOOTH_LINUX, 1, [Define if system supports Bluetooth stack for Linux]) fi - if (test "${usb_enable}" = "yes" && test "${usb_found}" = "yes"); then - AC_DEFINE(HAVE_USB, 1, [Define if system supports USB and it's enabled]) + if (test "${usb_enable}" = "yes" && (test "${usb_found}" = "yes" || test "${usb1_found}" = "yes")); then + AC_DEFINE(HAVE_USB, 1, [Define if system has libusb 0.x or libusb 1.0 and it's enabled]) + fi + + if (test "${usb_enable}" = "yes" && test "${usb1_found}" = "yes"); then + AC_DEFINE(HAVE_USB1, 1, [Define if system has libusb 1.0 and it's enabled]) fi AM_CONDITIONAL(GLIB, test "${glib_enable}" = "yes" && test "${glib_found}" = "yes") diff --git a/configure.ac b/configure.ac index 477a27d..8e09960 100644 --- a/configure.ac +++ b/configure.ac @@ -30,6 +30,7 @@ AC_PATH_WIN32 AC_PATH_IRDA AC_PATH_BLUETOOTH AC_PATH_USB +AC_PATH_USB1 AC_ARG_OPENOBEX diff --git a/doc/Doxyfile b/doc/Doxyfile index 41b820a..7b0b8ac 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -198,7 +198,7 @@ EXPAND_ONLY_PREDEF = YES SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = -PREDEFINED = "LIB_SYMBOL=" "CALLAPI=" "OPENOBEX_SYMBOL(retval)=retval" HAVE_IRDA HAVE_USB HAVE_BLUETOOTH +PREDEFINED = "LIB_SYMBOL=" "CALLAPI=" "OPENOBEX_SYMBOL(retval)=retval" HAVE_IRDA HAVE_USB HAVE_USB1 HAVE_BLUETOOTH EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index be9e955..dbbfb1f 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -197,7 +197,7 @@ EXPAND_ONLY_PREDEF = YES SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = -PREDEFINED = "LIB_SYMBOL=" "CALLAPI=" "OPENOBEX_SYMBOL(retval)=retval" HAVE_IRDA HAVE_USB HAVE_BLUETOOTH +PREDEFINED = "LIB_SYMBOL=" "CALLAPI=" "OPENOBEX_SYMBOL(retval)=retval" HAVE_IRDA HAVE_USB HAVE_USB1 HAVE_BLUETOOTH EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- diff --git a/lib/Makefile.am b/lib/Makefile.am index f45e7da..7510ee9 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -15,17 +15,18 @@ libopenobex_la_SOURCES = \ btobex.c btobex.h \ databuffer.c databuffer.h \ irda.h irda_wrap.h \ - usbobex.c usbobex.h \ + usbutils.c usbutils.h \ + usbobex.c usb1obex.c usbobex.h \ bluez_compat.h -libopenobex_la_CFLAGS = @CFLAG_VISIBILITY@ +libopenobex_la_CFLAGS = @CFLAG_VISIBILITY@ @USB1_CFLAGS@ libopenobex_la_LDFLAGS = \ -no-undefined \ -version-info 6:0:0 \ -export-symbols $(top_srcdir)/lib/obex.sym -libopenobex_la_LIBADD = @USB_LIBS@ @EXTRA_LIBS@ +libopenobex_la_LIBADD = @USB_LIBS@ @USB1_LIBS@ @EXTRA_LIBS@ INCLUDES = -I$(top_srcdir)/include diff --git a/lib/obex_transport.c b/lib/obex_transport.c index 690a79f..e3881e9 100644 --- a/lib/obex_transport.c +++ b/lib/obex_transport.c @@ -433,10 +433,19 @@ int obex_transport_write(obex_t *self, buf_t *msg) if (self->trans.connected != TRUE) break; DEBUG(4, "Endpoint %d\n", self->trans.self.usb.data_endpoint_write); +#ifdef HAVE_USB1 + int usberror = libusb_bulk_transfer(self->trans.self.usb.dev, + self->trans.self.usb.data_endpoint_write, + (unsigned char *) msg->data, msg->data_size, + &actual, USB_OBEX_TIMEOUT); + if (usberror) + actual = usberror; +#else actual = usb_bulk_write(self->trans.self.usb.dev, self->trans.self.usb.data_endpoint_write, (char *) msg->data, msg->data_size, USB_OBEX_TIMEOUT); +#endif break; #endif /*HAVE_USB*/ case OBEX_TRANS_CUSTOM: @@ -493,10 +502,20 @@ int obex_transport_read(obex_t *self, int max, uint8_t *buf, int buflen) if (self->trans.connected != TRUE) break; DEBUG(4, "Endpoint %d\n", self->trans.self.usb.data_endpoint_read); +#ifdef HAVE_USB1 + int usberror = libusb_bulk_transfer(self->trans.self.usb.dev, + self->trans.self.usb.data_endpoint_read, + buf_reserve_end(msg, self->mtu_rx), + self->mtu_rx, &actual, + USB_OBEX_TIMEOUT); + if (usberror) + actual = usberror; +#else actual = usb_bulk_read(self->trans.self.usb.dev, self->trans.self.usb.data_endpoint_read, buf_reserve_end(msg, self->mtu_rx), self->mtu_rx, USB_OBEX_TIMEOUT); +#endif buf_remove_end(msg, self->mtu_rx - actual); break; #endif /*HAVE_USB*/ diff --git a/lib/usb1obex.c b/lib/usb1obex.c new file mode 100644 index 0000000..1dffa27 --- /dev/null +++ b/lib/usb1obex.c @@ -0,0 +1,419 @@ +/** + \file usbobex.c + USB OBEX, USB transport for OBEX, libusb 1.x support. + OpenOBEX library - Free implementation of the Object Exchange protocol. + + Copyright (c) 2009 Alex Kanavin, All Rights Reserved. + + OpenOBEX 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.1 of + the License, or (at your option) any later version. + + This program 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 OpenOBEX. If not, see <http://www.gnu.org/>. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_USB1 + +#include <string.h> +#include <unistd.h> +#include <stdio.h> /* perror */ +#include <errno.h> /* errno and EADDRNOTAVAIL */ +#include <stdlib.h> + +#include <libusb.h> + +#include "obex_main.h" +#include "usbobex.h" +#include "usbutils.h" + +static struct libusb_context *libusb_ctx = NULL; + +/* + * 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) +{ + self->trans.self.usb = *intf; +} + +/* + * Helper function to usbobex_find_interfaces + */ +static void find_eps(struct obex_usb_intf_transport_t *intf, struct libusb_interface_descriptor data_intf, int *found_active, int *found_idle) +{ + struct libusb_endpoint_descriptor ep0, ep1; + + if (data_intf.bNumEndpoints == 2) { + ep0 = data_intf.endpoint[0]; + ep1 = data_intf.endpoint[1]; + if ((ep0.bEndpointAddress & LIBUSB_ENDPOINT_IN) && + ((ep0.bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK) && + !(ep1.bEndpointAddress & LIBUSB_ENDPOINT_IN) && + ((ep1.bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_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 & LIBUSB_ENDPOINT_IN) && + ((ep0.bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK) && + (ep1.bEndpointAddress & LIBUSB_ENDPOINT_IN) && + ((ep1.bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_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(const unsigned char *buffer, int buflen, struct libusb_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_OBEX_SERVICE_ID_TYPE: /* This one is handled later */ + 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 libusb_device_handle *usb_handle, char **string, int id) +{ + if (id) { + if ((*string = malloc(USB_MAX_STRING_SIZE)) == NULL) + return -ENOMEM; + *string[0] = '\0'; + return libusb_get_string_descriptor_ascii(usb_handle, id, (unsigned char*)*string, USB_MAX_STRING_SIZE); + } + + return 0; +} + +/* + * Helper function to usbobex_find_interfaces + */ +static struct obex_usb_intf_transport_t *check_intf(struct libusb_device *dev, + struct libusb_config_descriptor *conf_desc, int i, int a, + struct obex_usb_intf_transport_t *current) +{ + struct obex_usb_intf_transport_t *next = NULL; + if ((conf_desc->interface[i].altsetting[a].bInterfaceClass == USB_CDC_CLASS) + && (conf_desc->interface[i].altsetting[a].bInterfaceSubClass == USB_CDC_OBEX_SUBCLASS)) { + int err; + const unsigned char *buffer = conf_desc->interface[i].altsetting[a].extra; + int buflen = conf_desc->interface[i].altsetting[a].extra_length; + + next = malloc(sizeof(struct obex_usb_intf_transport_t)); + if (next == NULL) + return current; + next->device = dev; + libusb_ref_device(dev); + next->configuration = conf_desc->bConfigurationValue; + next->configuration_description = conf_desc->iConfiguration; + next->control_interface = conf_desc->interface[i].altsetting[a].bInterfaceNumber; + next->control_interface_description = conf_desc->interface[i].altsetting[a].iInterface; + next->control_setting = conf_desc->interface[i].altsetting[a].bAlternateSetting; + next->extra_descriptors = malloc(buflen); + if (next->extra_descriptors) + memcpy(next->extra_descriptors, buffer, buflen); + next->extra_descriptors_len = buflen; + + err = find_obex_data_interface(buffer, buflen, conf_desc, 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) +{ + int usbinit_error = 0; + struct obex_usb_intf_transport_t *current = NULL, *tmp = NULL; + int i, a, num; + obex_interface_t *intf_array = NULL; + + if (libusb_ctx == NULL) + usbinit_error = libusb_init(&libusb_ctx); + if (usbinit_error == 0) { + libusb_device **list; + size_t cnt_dev = libusb_get_device_list(libusb_ctx, &list); + size_t d = 0; + for (d = 0; d < cnt_dev; d++) { + struct libusb_config_descriptor *conf_desc; + if (libusb_get_active_config_descriptor(list[d], &conf_desc) == 0) { + for (i = 0; i < conf_desc->bNumInterfaces; i++) { + for (a = 0; a < conf_desc->interface[i].num_altsetting; a++) { + current = check_intf(list[d], conf_desc, i, a, current); + } + } + libusb_free_config_descriptor(conf_desc); + } + } + libusb_free_device_list(list, 1); + } + + 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.intf = current; + struct libusb_device_handle *usb_handle; + if (libusb_open(current->device, &usb_handle) == 0) { + struct libusb_device_descriptor dev_desc; + if (libusb_get_device_descriptor(current->device, &dev_desc) == 0) { + get_intf_string(usb_handle, &intf_array[num].usb.manufacturer, + dev_desc.iManufacturer); + get_intf_string(usb_handle, &intf_array[num].usb.product, + dev_desc.iProduct); + get_intf_string(usb_handle, &intf_array[num].usb.serial, + dev_desc.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); + } + find_obex_service_descriptor(current->extra_descriptors, + current->extra_descriptors_len, + &intf_array[num].usb.service); + libusb_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 < num; i++) { + 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.service); + free(intf[i].usb.intf->extra_descriptors); + libusb_unref_device(intf[i].usb.intf->device); + free(intf[i].usb.intf); + } + + free(intf); + if (libusb_ctx) + libusb_exit(libusb_ctx); + +} + +/* + * Function usbobex_connect_request (self) + * + * Open the USB connection + * + */ +int usbobex_connect_request(obex_t *self) +{ + int ret; + + DEBUG(4, "\n"); + + ret = libusb_open(self->trans.self.usb.device, &self->trans.self.usb.dev); + if (ret != 0) + return ret; + + ret = libusb_claim_interface(self->trans.self.usb.dev, self->trans.self.usb.control_interface); + if (ret < 0) { + DEBUG(4, "Can't claim control interface %d", ret); + goto err1; + } + + ret = libusb_set_interface_alt_setting(self->trans.self.usb.dev, self->trans.self.usb.control_interface, self->trans.self.usb.control_setting); + if (ret < 0) { + DEBUG(4, "Can't set control setting %d", ret); + goto err2; + } + + ret = libusb_claim_interface(self->trans.self.usb.dev, self->trans.self.usb.data_interface); + if (ret < 0) { + DEBUG(4, "Can't claim data interface %d", ret); + goto err2; + } + + ret = libusb_set_interface_alt_setting(self->trans.self.usb.dev, self->trans.self.usb.data_interface, 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: + libusb_release_interface(self->trans.self.usb.dev, self->trans.self.usb.data_interface); +err2: + libusb_release_interface(self->trans.self.usb.dev, self->trans.self.usb.control_interface); +err1: + libusb_close(self->trans.self.usb.dev); + return ret; +} + +/* + * Function usbobex_disconnect_request (self) + * + * Shutdown the USB link + * + */ +int usbobex_disconnect_request(obex_t *self) +{ + int ret; + if (self->trans.connected == FALSE) + return 0; + + DEBUG(4, "\n"); + + libusb_clear_halt(self->trans.self.usb.dev, self->trans.self.usb.data_endpoint_read); + libusb_clear_halt(self->trans.self.usb.dev, self->trans.self.usb.data_endpoint_write); + + ret = libusb_set_interface_alt_setting(self->trans.self.usb.dev, self->trans.self.usb.data_interface, self->trans.self.usb.data_idle_setting); + if (ret < 0) + DEBUG(4, "Can't set data idle setting %d", ret); + ret = libusb_release_interface(self->trans.self.usb.dev, self->trans.self.usb.data_interface); + if (ret < 0) + DEBUG(4, "Can't release data interface %d", ret); + ret = libusb_release_interface(self->trans.self.usb.dev, self->trans.self.usb.control_interface); + if (ret < 0) + DEBUG(4, "Can't release control interface %d", ret); + libusb_close(self->trans.self.usb.dev); + return 1; +} + + +#endif /* HAVE_USB1 */ diff --git a/lib/usbobex.c b/lib/usbobex.c index b87458d..2ad91a0 100644 --- a/lib/usbobex.c +++ b/lib/usbobex.c @@ -23,7 +23,7 @@ #include <config.h> #endif -#ifdef HAVE_USB +#if defined HAVE_USB && !defined HAVE_USB1 #ifdef _WIN32 #include <winsock2.h> @@ -43,6 +43,7 @@ #include "obex_main.h" #include "usbobex.h" +#include "usbutils.h" /* * Function usbobex_prepare_connect (self, interface) @@ -203,7 +204,9 @@ static struct obex_usb_intf_transport_t *check_intf(struct usb_device *dev, 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; - next->extra_descriptors = buffer; + next->extra_descriptors = malloc(buflen); + if (next->extra_descriptors) + memcpy(next->extra_descriptors, buffer, buflen); next->extra_descriptors_len = buflen; err = find_obex_data_interface(buffer, buflen, dev->config[c], next); @@ -222,53 +225,6 @@ static struct obex_usb_intf_transport_t *check_intf(struct usb_device *dev, } /* - * Helper function to usbobex_find_interfaces - */ -static void find_obex_service_descriptor(unsigned char *buffer, int buflen, obex_usb_intf_service_t **service) -{ - if (!buffer) { - DEBUG(2, "Weird descriptor references"); - return ; - } - while (buflen > 0) { - if (buffer[1] != USB_DT_CS_INTERFACE) { - DEBUG(2, "skipping garbage"); - goto next_desc; - } - switch (buffer[2]) { - case CDC_OBEX_SERVICE_ID_TYPE: /* we've found it */ - if (buflen < 22) /* Check descriptor size */ - DEBUG(2, "Invalid service id descriptor"); - else if (*service == NULL) { - *service = malloc(sizeof(obex_usb_intf_service_t)); - if (*service != NULL) { - const uint8_t default_uuid[16] = WMC_DEFAULT_OBEX_SERVER_UUID; - (*service)->role = buffer[3]; - memcpy((*service)->uuid, buffer+4, 16); - (*service)->version = (buffer[20]<<8)|(buffer[21]); - if (memcmp((*service)->uuid, default_uuid, 16) == 0 ) - (*service)->is_default_uuid = 1; - else - (*service)->is_default_uuid = 0; - } - } - break; - case CDC_OBEX_TYPE: /* maybe check version */ - case CDC_UNION_TYPE: - case CDC_HEADER_TYPE: - break; - default: - DEBUG(2, "Ignoring extra header, type %d, length %d", buffer[2], buffer[0]); - break; - } -next_desc: - buflen -= buffer[0]; - buffer += buffer[0]; - } -} - - -/* * Function usbobex_find_interfaces () * * Find available USBOBEX interfaces on the system @@ -374,6 +330,7 @@ void usbobex_free_interfaces(int num, obex_interface_t *intf) free(intf[i].usb.data_interface_idle); free(intf[i].usb.data_interface_active); free(intf[i].usb.service); + free(intf[i].usb.intf->extra_descriptors); free(intf[i].usb.intf); } diff --git a/lib/usbobex.h b/lib/usbobex.h index 9fb1797..80203ae 100644 --- a/lib/usbobex.h +++ b/lib/usbobex.h @@ -23,12 +23,16 @@ #define USBOBEX_H #include <openobex/obex_const.h> + +#ifdef HAVE_USB1 +#include <libusb.h> +#else #include <usb.h> +#endif /* 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 */ @@ -37,7 +41,7 @@ struct obex_usb_intf_transport_t { * If non-zero, use usb_get_string_simple() from * libusb to retrieve human-readable description */ - unsigned char *extra_descriptors; /* Extra master interface descriptors */ + char *extra_descriptors; /* Extra master interface descriptors */ int extra_descriptors_len; /* Length of extra descriptors */ int data_interface; /* OBEX data/slave interface */ int data_idle_setting; /* OBEX data/slave idle setting */ @@ -48,7 +52,13 @@ struct obex_usb_intf_transport_t { * 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; /* libusb handler */ +#ifdef HAVE_USB1 + struct libusb_device *device; /* libusb 1.x device */ + struct libusb_device_handle *dev; /* libusb 1.x device handle */ +#else + struct usb_device *device; /* libusb 0.x device */ + usb_dev_handle *dev; /* libusb 0.x device handle */ +#endif }; /* "Union Functional Descriptor" from CDC spec 5.2.3.X diff --git a/lib/usbutils.c b/lib/usbutils.c new file mode 100644 index 0000000..92bb4bf --- /dev/null +++ b/lib/usbutils.c @@ -0,0 +1,82 @@ +/** + \file usbutils.c + USB OBEX, USB transport for OBEX, support functions. + OpenOBEX library - Free implementation of the Object Exchange protocol. + + Copyright (c) 2009 Alex Kanavin, All Rights Reserved. + + OpenOBEX 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.1 of + the License, or (at your option) any later version. + + This program 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 OpenOBEX. If not, see <http://www.gnu.org/>. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_USB + +#include <string.h> +#include <unistd.h> +#include <stdio.h> /* perror */ +#include <errno.h> /* errno and EADDRNOTAVAIL */ +#include <stdlib.h> +#include "obex_main.h" +#include "usbobex.h" + +/* + * Helper function to usbobex_find_interfaces + */ +void find_obex_service_descriptor(const char *buffer, int buflen, obex_usb_intf_service_t **service) +{ + if (!buffer) { + DEBUG(2, "Weird descriptor references"); + return ; + } + while (buflen > 0) { + if (buffer[1] != USB_DT_CS_INTERFACE) { + DEBUG(2, "skipping garbage"); + goto next_desc; + } + switch (buffer[2]) { + case CDC_OBEX_SERVICE_ID_TYPE: /* we've found it */ + if (buflen < 22) /* Check descriptor size */ + DEBUG(2, "Invalid service id descriptor"); + else if (*service == NULL) { + *service = malloc(sizeof(obex_usb_intf_service_t)); + if (*service != NULL) { + const uint8_t default_uuid[16] = WMC_DEFAULT_OBEX_SERVER_UUID; + (*service)->role = buffer[3]; + memcpy((*service)->uuid, buffer+4, 16); + (*service)->version = (buffer[20]<<8)|(buffer[21]); + if (memcmp((*service)->uuid, default_uuid, 16) == 0 ) + (*service)->is_default_uuid = 1; + else + (*service)->is_default_uuid = 0; + } + } + break; + case CDC_OBEX_TYPE: /* maybe check version */ + case CDC_UNION_TYPE: + case CDC_HEADER_TYPE: + break; + default: + DEBUG(2, "Ignoring extra header, type %d, length %d", buffer[2], buffer[0]); + break; + } +next_desc: + buflen -= buffer[0]; + buffer += buffer[0]; + } +} + +#endif diff --git a/lib/usbutils.h b/lib/usbutils.h new file mode 100644 index 0000000..02cb6e3 --- /dev/null +++ b/lib/usbutils.h @@ -0,0 +1,30 @@ +/** + \file usbutils.h + USB OBEX, USB transport for OBEX, support functions. + OpenOBEX library - Free implementation of the Object Exchange protocol. + + Copyright (c) 2009 Alex Kanavin, All Rights Reserved. + + OpenOBEX 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.1 of + the License, or (at your option) any later version. + + This program 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 OpenOBEX. If not, see <http://www.gnu.org/>. + */ + +#ifndef USBUTILS_H +#define USBUTILS_H + +#include <openobex/obex_const.h> + +void find_obex_service_descriptor(const char *buffer, int buflen, obex_usb_intf_service_t **service); + +#endif + -- 1.6.0.6 ------------------------------------------------------------------------------ Crystal Reports - New Free Runtime and 30 Day Trial Check out the new simplified licensing option that enables unlimited royalty-free distribution of the report engine for externally facing server and web deployment. http://p.sf.net/sfu/businessobjects _______________________________________________ Openobex-users mailing list Openobex-users@lists.sourceforge.net http://lists.sourceforge.net/lists/listinfo/openobex-users