aboutsummaryrefslogtreecommitdiff
path: root/lib/libusb/libusb10_desc.c
diff options
context:
space:
mode:
authorAlfred Perlstein <alfred@FreeBSD.org>2009-07-30 00:11:41 +0000
committerAlfred Perlstein <alfred@FreeBSD.org>2009-07-30 00:11:41 +0000
commit390065b18e0ee636279b106ff06f0a1463589ab1 (patch)
tree35d9a81dcb5e49cb309382bf22adb81c31afeef6 /lib/libusb/libusb10_desc.c
parented190ad06a7017afbfcb1f517981119c188233c4 (diff)
downloadsrc-390065b18e0ee636279b106ff06f0a1463589ab1.tar.gz
src-390065b18e0ee636279b106ff06f0a1463589ab1.zip
LibUSB v1.0:
- Significantly improve libusb10 support. - Many minor issues fixed. - P4 ID: 166189, 165853, 165991, 166052, 166069 Submitted by: hps Approved by: re
Notes
Notes: svn path=/head/; revision=195957
Diffstat (limited to 'lib/libusb/libusb10_desc.c')
-rw-r--r--lib/libusb/libusb10_desc.c264
1 files changed, 135 insertions, 129 deletions
diff --git a/lib/libusb/libusb10_desc.c b/lib/libusb/libusb10_desc.c
index b218c2e77171..c43443af939b 100644
--- a/lib/libusb/libusb10_desc.c
+++ b/lib/libusb/libusb10_desc.c
@@ -24,10 +24,10 @@
* SUCH DAMAGE.
*/
-#include <sys/queue.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
+#include <sys/queue.h>
#include "libusb20.h"
#include "libusb20_desc.h"
@@ -38,16 +38,11 @@
/* USB descriptors */
int
-libusb_get_device_descriptor(libusb_device * dev,
+libusb_get_device_descriptor(libusb_device *dev,
struct libusb_device_descriptor *desc)
{
struct LIBUSB20_DEVICE_DESC_DECODED *pdesc;
struct libusb20_device *pdev;
- libusb_context *ctx;
-
- ctx = NULL;
- GET_CONTEXT(ctx);
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_descriptor enter");
if ((dev == NULL) || (desc == NULL))
return (LIBUSB_ERROR_INVALID_PARAM);
@@ -70,54 +65,47 @@ libusb_get_device_descriptor(libusb_device * dev,
desc->iSerialNumber = pdesc->iSerialNumber;
desc->bNumConfigurations = pdesc->bNumConfigurations;
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_descriptor leave");
return (0);
}
int
-libusb_get_active_config_descriptor(libusb_device * dev,
+libusb_get_active_config_descriptor(libusb_device *dev,
struct libusb_config_descriptor **config)
{
struct libusb20_device *pdev;
- libusb_context *ctx;
- uint8_t idx;
-
- ctx = NULL;
- GET_CONTEXT(ctx);
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_active_config_descriptor enter");
+ uint8_t config_index;
pdev = dev->os_priv;
- idx = libusb20_dev_get_config_index(pdev);
+ config_index = libusb20_dev_get_config_index(pdev);
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_active_config_descriptor leave");
- return (libusb_get_config_descriptor(dev, idx, config));
+ return (libusb_get_config_descriptor(dev, config_index, config));
}
-/*
- * XXX Need to check if extra need a dup because
- * XXX free pconf could free this char *
- */
int
-libusb_get_config_descriptor(libusb_device * dev, uint8_t config_index,
+libusb_get_config_descriptor(libusb_device *dev, uint8_t config_index,
struct libusb_config_descriptor **config)
{
struct libusb20_device *pdev;
struct libusb20_config *pconf;
struct libusb20_interface *pinf;
struct libusb20_endpoint *pend;
- libusb_interface_descriptor *ifd;
- libusb_endpoint_descriptor *endd;
- libusb_context *ctx;
- uint8_t nif, nend, nalt, i, j, k;
- uint32_t if_idx, endp_idx;
-
- ctx = NULL;
- GET_CONTEXT(ctx);
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_config_descriptor enter");
+ struct libusb_config_descriptor *pconfd;
+ struct libusb_interface_descriptor *ifd;
+ struct libusb_endpoint_descriptor *endd;
+ uint8_t *pextra;
+ uint16_t nextra;
+ uint8_t nif;
+ uint8_t nep;
+ uint8_t nalt;
+ uint8_t i;
+ uint8_t j;
+ uint8_t k;
if (dev == NULL || config == NULL)
return (LIBUSB_ERROR_INVALID_PARAM);
+ *config = NULL;
+
pdev = dev->os_priv;
pconf = libusb20_dev_alloc_config(pdev, config_index);
@@ -125,75 +113,101 @@ libusb_get_config_descriptor(libusb_device * dev, uint8_t config_index,
return (LIBUSB_ERROR_NOT_FOUND);
nalt = nif = pconf->num_interface;
- nend = 0;
- for (i = 0 ; i < nif ; i++) {
- if (pconf->interface[i].num_altsetting > 0)
- {
- nalt += pconf->interface[i].num_altsetting;
- for (j = 0 ; j < nalt ; j++) {
- nend += pconf->interface[i].altsetting[j].num_endpoints;
+ nep = 0;
+ nextra = pconf->extra.len;
+
+ for (i = 0; i < nif; i++) {
+
+ pinf = pconf->interface + i;
+ nextra += pinf->extra.len;
+ nep += pinf->num_endpoints;
+ k = pinf->num_endpoints;
+ pend = pinf->endpoints;
+ while (k--) {
+ nextra += pend->extra.len;
+ pend++;
+ }
+
+ j = pinf->num_altsetting;
+ nalt += pinf->num_altsetting;
+ pinf = pinf->altsetting;
+ while (j--) {
+ nextra += pinf->extra.len;
+ nep += pinf->num_endpoints;
+ k = pinf->num_endpoints;
+ pend = pinf->endpoints;
+ while (k--) {
+ nextra += pend->extra.len;
+ pend++;
}
+ pinf++;
}
- nend += pconf->interface[i].num_endpoints;
}
- *config = malloc(sizeof(libusb_config_descriptor) +
+ nextra = nextra +
+ (1 * sizeof(libusb_config_descriptor)) +
(nif * sizeof(libusb_interface)) +
(nalt * sizeof(libusb_interface_descriptor)) +
- (nend * sizeof(libusb_endpoint_descriptor)));
- if (*config == NULL) {
+ (nep * sizeof(libusb_endpoint_descriptor));
+
+ pconfd = malloc(nextra);
+
+ if (pconfd == NULL) {
free(pconf);
return (LIBUSB_ERROR_NO_MEM);
}
+ /* make sure memory is clean */
+ memset(pconfd, 0, nextra);
- (*config)->interface = (libusb_interface *)(*config +
+ pconfd->interface = (libusb_interface *) (pconfd +
sizeof(libusb_config_descriptor));
- for (i = if_idx = endp_idx = 0 ; i < nif ; if_idx, i++) {
- (*config)->interface[i].altsetting = (libusb_interface_descriptor *)
- (*config + sizeof(libusb_config_descriptor) +
- (nif * sizeof(libusb_interface)) +
- (if_idx * sizeof(libusb_interface_descriptor)));
- (*config)->interface[i].altsetting[0].endpoint =
- (libusb_endpoint_descriptor *) (*config +
- sizeof(libusb_config_descriptor) +
- (nif * sizeof(libusb_interface)) +
- (nalt * sizeof(libusb_interface_descriptor)) +
- (endp_idx * sizeof(libusb_endpoint_descriptor)));
- endp_idx += pconf->interface[i].num_endpoints;
-
- if (pconf->interface[i].num_altsetting > 0)
- {
- for (j = 0 ; j < pconf->interface[i].num_altsetting ; j++, if_idx++) {
- (*config)->interface[i].altsetting[j + 1].endpoint =
- (libusb_endpoint_descriptor *) (*config +
- sizeof(libusb_config_descriptor) +
- (nif * sizeof(libusb_interface)) +
- (nalt * sizeof(libusb_interface_descriptor)) +
- (endp_idx * sizeof(libusb_endpoint_descriptor)));
- endp_idx += pconf->interface[i].altsetting[j].num_endpoints;
- }
+
+ ifd = (libusb_interface_descriptor *) (pconfd->interface + nif);
+ endd = (libusb_endpoint_descriptor *) (ifd + nalt);
+ pextra = (uint8_t *)(endd + nep);
+
+ /* fill in config descriptor */
+
+ pconfd->bLength = pconf->desc.bLength;
+ pconfd->bDescriptorType = pconf->desc.bDescriptorType;
+ pconfd->wTotalLength = pconf->desc.wTotalLength;
+ pconfd->bNumInterfaces = pconf->desc.bNumInterfaces;
+ pconfd->bConfigurationValue = pconf->desc.bConfigurationValue;
+ pconfd->iConfiguration = pconf->desc.iConfiguration;
+ pconfd->bmAttributes = pconf->desc.bmAttributes;
+ pconfd->MaxPower = pconf->desc.bMaxPower;
+
+ if (pconf->extra.len != 0) {
+ pconfd->extra_length = pconf->extra.len;
+ pconfd->extra = pextra;
+ memcpy(pextra, pconf->extra.ptr, pconfd->extra_length);
+ pextra += pconfd->extra_length;
+ }
+ /* setup all interface and endpoint pointers */
+
+ for (i = 0; i < nif; i++) {
+
+ pconfd->interface[i].altsetting = ifd;
+ ifd->endpoint = endd;
+ endd += pconf->interface[i].num_endpoints;
+ ifd++;
+
+ for (j = 0; j < pconf->interface[i].num_altsetting; j++) {
+ ifd->endpoint = endd;
+ endd += pconf->interface[i].altsetting[j].num_endpoints;
+ ifd++;
}
}
- (*config)->bLength = pconf->desc.bLength;
- (*config)->bDescriptorType = pconf->desc.bDescriptorType;
- (*config)->wTotalLength = pconf->desc.wTotalLength;
- (*config)->bNumInterfaces = pconf->desc.bNumInterfaces;
- (*config)->bConfigurationValue = pconf->desc.bConfigurationValue;
- (*config)->iConfiguration = pconf->desc.iConfiguration;
- (*config)->bmAttributes = pconf->desc.bmAttributes;
- (*config)->MaxPower = pconf->desc.bMaxPower;
- (*config)->extra_length = pconf->extra.len;
- if ((*config)->extra_length != 0)
- (*config)->extra = pconf->extra.ptr;
-
- for (i = 0 ; i < nif ; i++) {
+ /* fill in all interface and endpoint data */
+
+ for (i = 0; i < nif; i++) {
pinf = &pconf->interface[i];
- (*config)->interface[i].num_altsetting = pinf->num_altsetting + 1;
- for (j = 0 ; j < (*config)->interface[i].num_altsetting ; j++) {
+ pconfd->interface[i].num_altsetting = pinf->num_altsetting + 1;
+ for (j = 0; j < pconfd->interface[i].num_altsetting; j++) {
if (j != 0)
pinf = &pconf->interface[i].altsetting[j - 1];
- ifd = &(*config)->interface[i].altsetting[j];
+ ifd = &pconfd->interface[i].altsetting[j];
ifd->bLength = pinf->desc.bLength;
ifd->bDescriptorType = pinf->desc.bDescriptorType;
ifd->bInterfaceNumber = pinf->desc.bInterfaceNumber;
@@ -203,10 +217,13 @@ libusb_get_config_descriptor(libusb_device * dev, uint8_t config_index,
ifd->bInterfaceSubClass = pinf->desc.bInterfaceSubClass;
ifd->bInterfaceProtocol = pinf->desc.bInterfaceProtocol;
ifd->iInterface = pinf->desc.iInterface;
- ifd->extra_length = pinf->extra.len;
- if (ifd->extra_length != 0)
- ifd->extra = pinf->extra.ptr;
- for (k = 0 ; k < pinf->num_endpoints ; k++) {
+ if (pinf->extra.len != 0) {
+ ifd->extra_length = pinf->extra.len;
+ ifd->extra = pextra;
+ memcpy(pextra, pinf->extra.ptr, pinf->extra.len);
+ pextra += pinf->extra.len;
+ }
+ for (k = 0; k < pinf->num_endpoints; k++) {
pend = &pinf->endpoints[k];
endd = &ifd->endpoint[k];
endd->bLength = pend->desc.bLength;
@@ -217,82 +234,71 @@ libusb_get_config_descriptor(libusb_device * dev, uint8_t config_index,
endd->bInterval = pend->desc.bInterval;
endd->bRefresh = pend->desc.bRefresh;
endd->bSynchAddress = pend->desc.bSynchAddress;
- endd->extra_length = pend->extra.len;
- if (endd->extra_length != 0)
- endd->extra = pend->extra.ptr;
+ if (pend->extra.len != 0) {
+ endd->extra_length = pend->extra.len;
+ endd->extra = pextra;
+ memcpy(pextra, pend->extra.ptr, pend->extra.len);
+ pextra += pend->extra.len;
+ }
}
- }
+ }
}
free(pconf);
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_config_descriptor leave");
- return (0);
+
+ *config = pconfd;
+
+ return (0); /* success */
}
int
-libusb_get_config_descriptor_by_value(libusb_device * dev,
+libusb_get_config_descriptor_by_value(libusb_device *dev,
uint8_t bConfigurationValue, struct libusb_config_descriptor **config)
{
struct LIBUSB20_DEVICE_DESC_DECODED *pdesc;
struct libusb20_device *pdev;
- struct libusb20_config *pconf;
- libusb_context *ctx;
int i;
-
- ctx = NULL;
- GET_CONTEXT(ctx);
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_config_descriptor_by_value enter");
+ int err;
if (dev == NULL || config == NULL)
return (LIBUSB_ERROR_INVALID_PARAM);
-
+
pdev = dev->os_priv;
pdesc = libusb20_dev_get_device_desc(pdev);
- for (i = 0 ; i < pdesc->bNumConfigurations ; i++) {
- pconf = libusb20_dev_alloc_config(pdev, i);
- if (pconf->desc.bConfigurationValue == bConfigurationValue) {
- free(pconf);
- return libusb_get_config_descriptor(dev, i, config);
+ for (i = 0; i < pdesc->bNumConfigurations; i++) {
+ err = libusb_get_config_descriptor(dev, i, config);
+ if (err)
+ return (err);
- }
- free(pconf);
+ if ((*config)->bConfigurationValue == bConfigurationValue)
+ return (0); /* success */
+
+ libusb_free_config_descriptor(*config);
}
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_config_descriptor_by_value leave");
+ *config = NULL;
+
return (LIBUSB_ERROR_NOT_FOUND);
}
void
libusb_free_config_descriptor(struct libusb_config_descriptor *config)
{
- libusb_context *ctx;
-
- ctx = NULL;
- GET_CONTEXT(ctx);
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_config_descriptor enter");
-
free(config);
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_config_descriptor leave");
}
int
-libusb_get_string_descriptor_ascii(libusb_device_handle * dev,
+libusb_get_string_descriptor_ascii(libusb_device_handle *pdev,
uint8_t desc_index, unsigned char *data, int length)
{
- struct libusb20_device *pdev;
- libusb_context *ctx;
-
- ctx = NULL;
- GET_CONTEXT(ctx);
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_string_descriptor_ascii enter");
-
- if (dev == NULL || data == NULL)
+ if (pdev == NULL || data == NULL || length < 1)
return (LIBUSB20_ERROR_INVALID_PARAM);
- pdev = dev->os_priv;
- DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_string_descriptor_ascii leave");
- if (libusb20_dev_req_string_simple_sync(pdev, desc_index,
+ /* put some default data into the destination buffer */
+ data[0] = 0;
+
+ if (libusb20_dev_req_string_simple_sync(pdev, desc_index,
data, length) == 0)
return (strlen(data));