--- 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 b85d8a4..c926503 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -177,6 +177,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) @@ -282,8 +299,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 79cd5e6..cb57efe 100644 --- a/configure.ac +++ b/configure.ac @@ -28,6 +28,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 ------------------------------------------------------------------------------ Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM) software. With Adobe AIR, Ajax developers can use existing skills and code to build responsive, highly engaging applications that combine the power of local resources and data with the reach of the web. Download the Adobe AIR SDK and Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com _______________________________________________ Openobex-users mailing list Openobex-users@lists.sourceforge.net http://lists.sourceforge.net/lists/listinfo/openobex-users