libusb10_desc.c revision 194676
1250003Sadrian/* $FreeBSD: head/lib/libusb/libusb10_desc.c 194676 2009-06-23 01:04:58Z thompsa $ */ 2250003Sadrian/*- 3250003Sadrian * Copyright (c) 2009 Sylvestre Gallon. All rights reserved. 4250003Sadrian * 5250003Sadrian * Redistribution and use in source and binary forms, with or without 6250003Sadrian * modification, are permitted provided that the following conditions 7250003Sadrian * are met: 8250003Sadrian * 1. Redistributions of source code must retain the above copyright 9250003Sadrian * notice, this list of conditions and the following disclaimer. 10250003Sadrian * 2. Redistributions in binary form must reproduce the above copyright 11250003Sadrian * notice, this list of conditions and the following disclaimer in the 12250003Sadrian * documentation and/or other materials provided with the distribution. 13250003Sadrian * 14250003Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15250003Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16250003Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17250003Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18250003Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19250003Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20250003Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21250003Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22250003Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23250003Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24250003Sadrian * SUCH DAMAGE. 25250003Sadrian */ 26250008Sadrian 27250003Sadrian#include <sys/queue.h> 28250003Sadrian#include <stdlib.h> 29250003Sadrian#include <stdio.h> 30250003Sadrian#include <pthread.h> 31250003Sadrian 32250003Sadrian#include "libusb20.h" 33250003Sadrian#include "libusb20_desc.h" 34250003Sadrian#include "libusb20_int.h" 35250003Sadrian#include "libusb.h" 36250003Sadrian#include "libusb10.h" 37250003Sadrian 38250003Sadrian/* USB descriptors */ 39250003Sadrian 40250003Sadrianint 41250003Sadrianlibusb_get_device_descriptor(libusb_device * dev, 42250003Sadrian struct libusb_device_descriptor *desc) 43250003Sadrian{ 44250003Sadrian struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 45250003Sadrian struct libusb20_device *pdev; 46250003Sadrian libusb_context *ctx; 47250003Sadrian 48250008Sadrian ctx = NULL; 49250003Sadrian GET_CONTEXT(ctx); 50250003Sadrian dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_descriptor enter"); 51250008Sadrian 52250003Sadrian if ((dev == NULL) || (desc == NULL)) 53250003Sadrian return (LIBUSB_ERROR_INVALID_PARAM); 54250003Sadrian 55250003Sadrian pdev = dev->os_priv; 56250003Sadrian pdesc = libusb20_dev_get_device_desc(pdev); 57250003Sadrian 58250003Sadrian desc->bLength = pdesc->bLength; 59250003Sadrian desc->bDescriptorType = pdesc->bDescriptorType; 60250003Sadrian desc->bcdUSB = pdesc->bcdUSB; 61250003Sadrian desc->bDeviceClass = pdesc->bDeviceClass; 62250003Sadrian desc->bDeviceSubClass = pdesc->bDeviceSubClass; 63250003Sadrian desc->bDeviceProtocol = pdesc->bDeviceProtocol; 64250003Sadrian desc->bMaxPacketSize0 = pdesc->bMaxPacketSize0; 65250003Sadrian desc->idVendor = pdesc->idVendor; 66250003Sadrian desc->idProduct = pdesc->idProduct; 67250003Sadrian desc->bcdDevice = pdesc->bcdDevice; 68250003Sadrian desc->iManufacturer = pdesc->iManufacturer; 69250003Sadrian desc->iProduct = pdesc->iProduct; 70250003Sadrian desc->iSerialNumber = pdesc->iSerialNumber; 71250003Sadrian desc->bNumConfigurations = pdesc->bNumConfigurations; 72250003Sadrian 73250003Sadrian dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_descriptor leave"); 74250003Sadrian return (0); 75250003Sadrian} 76250003Sadrian 77250003Sadrianint 78250003Sadrianlibusb_get_active_config_descriptor(libusb_device * dev, 79250003Sadrian struct libusb_config_descriptor **config) 80250003Sadrian{ 81250003Sadrian struct libusb20_device *pdev; 82250003Sadrian libusb_context *ctx; 83250003Sadrian uint8_t idx; 84250003Sadrian 85250003Sadrian ctx = NULL; 86250003Sadrian GET_CONTEXT(ctx); 87250003Sadrian dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_active_config_descriptor enter"); 88250003Sadrian 89250003Sadrian pdev = dev->os_priv; 90250003Sadrian idx = libusb20_dev_get_config_index(pdev); 91250003Sadrian 92250003Sadrian dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_active_config_descriptor leave"); 93250003Sadrian return (libusb_get_config_descriptor(dev, idx, config)); 94250003Sadrian} 95250003Sadrian 96250003Sadrian/* 97250003Sadrian * XXX Need to check if extra need a dup because 98250003Sadrian * XXX free pconf could free this char * 99250003Sadrian */ 100250003Sadrianint 101250003Sadrianlibusb_get_config_descriptor(libusb_device * dev, uint8_t config_index, 102250003Sadrian struct libusb_config_descriptor **config) 103250003Sadrian{ 104250003Sadrian struct libusb20_device *pdev; 105250003Sadrian struct libusb20_config *pconf; 106250003Sadrian struct libusb20_interface *pinf; 107250003Sadrian struct libusb20_endpoint *pend; 108250003Sadrian libusb_interface_descriptor *ifd; 109250003Sadrian libusb_endpoint_descriptor *endd; 110250003Sadrian libusb_context *ctx; 111250003Sadrian uint8_t nif, nend, nalt, i, j, k; 112250003Sadrian uint32_t if_idx, endp_idx; 113250003Sadrian 114250003Sadrian ctx = NULL; 115250003Sadrian GET_CONTEXT(ctx); 116250003Sadrian dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_config_descriptor enter"); 117250003Sadrian 118250003Sadrian if (dev == NULL || config == NULL) 119250003Sadrian return (LIBUSB_ERROR_INVALID_PARAM); 120250003Sadrian 121250003Sadrian pdev = dev->os_priv; 122250003Sadrian pconf = libusb20_dev_alloc_config(pdev, config_index); 123250003Sadrian 124250003Sadrian if (pconf == NULL) 125250003Sadrian return (LIBUSB_ERROR_NOT_FOUND); 126250003Sadrian 127250003Sadrian nalt = nif = pconf->num_interface; 128250003Sadrian nend = 0; 129250003Sadrian for (i = 0 ; i < nif ; i++) { 130250003Sadrian if (pconf->interface[i].num_altsetting > 0) 131250003Sadrian { 132250003Sadrian nalt += pconf->interface[i].num_altsetting; 133250003Sadrian for (j = 0 ; j < nalt ; j++) { 134250003Sadrian nend += pconf->interface[i].altsetting[j].num_endpoints; 135250003Sadrian } 136250003Sadrian } 137250003Sadrian nend += pconf->interface[i].num_endpoints; 138250003Sadrian } 139250003Sadrian 140250003Sadrian *config = malloc(sizeof(libusb_config_descriptor) + 141250003Sadrian (nif * sizeof(libusb_interface)) + 142250003Sadrian (nalt * sizeof(libusb_interface_descriptor)) + 143250003Sadrian (nend * sizeof(libusb_endpoint_descriptor))); 144250003Sadrian if (*config == NULL) { 145250003Sadrian free(pconf); 146250003Sadrian return (LIBUSB_ERROR_NO_MEM); 147250003Sadrian } 148250003Sadrian 149250003Sadrian (*config)->interface = (libusb_interface *)(*config + 150250003Sadrian sizeof(libusb_config_descriptor)); 151250003Sadrian for (i = if_idx = endp_idx = 0 ; i < nif ; if_idx, i++) { 152250003Sadrian (*config)->interface[i].altsetting = (libusb_interface_descriptor *) 153250003Sadrian (*config + sizeof(libusb_config_descriptor) + 154250003Sadrian (nif * sizeof(libusb_interface)) + 155250003Sadrian (if_idx * sizeof(libusb_interface_descriptor))); 156250003Sadrian (*config)->interface[i].altsetting[0].endpoint = 157250003Sadrian (libusb_endpoint_descriptor *) (*config + 158250003Sadrian sizeof(libusb_config_descriptor) + 159250003Sadrian (nif * sizeof(libusb_interface)) + 160250003Sadrian (nalt * sizeof(libusb_interface_descriptor)) + 161250003Sadrian (endp_idx * sizeof(libusb_endpoint_descriptor))); 162250003Sadrian endp_idx += pconf->interface[i].num_endpoints; 163250003Sadrian 164250003Sadrian if (pconf->interface[i].num_altsetting > 0) 165250008Sadrian { 166250003Sadrian for (j = 0 ; j < pconf->interface[i].num_altsetting ; j++, if_idx++) { 167250003Sadrian (*config)->interface[i].altsetting[j + 1].endpoint = 168250003Sadrian (libusb_endpoint_descriptor *) (*config + 169250003Sadrian sizeof(libusb_config_descriptor) + 170250003Sadrian (nif * sizeof(libusb_interface)) + 171250003Sadrian (nalt * sizeof(libusb_interface_descriptor)) + 172250003Sadrian (endp_idx * sizeof(libusb_endpoint_descriptor))); 173250003Sadrian endp_idx += pconf->interface[i].altsetting[j].num_endpoints; 174250003Sadrian } 175250003Sadrian } 176250003Sadrian } 177250003Sadrian 178250003Sadrian (*config)->bLength = pconf->desc.bLength; 179250003Sadrian (*config)->bDescriptorType = pconf->desc.bDescriptorType; 180250003Sadrian (*config)->wTotalLength = pconf->desc.wTotalLength; 181250003Sadrian (*config)->bNumInterfaces = pconf->desc.bNumInterfaces; 182250003Sadrian (*config)->bConfigurationValue = pconf->desc.bConfigurationValue; 183250003Sadrian (*config)->iConfiguration = pconf->desc.iConfiguration; 184250003Sadrian (*config)->bmAttributes = pconf->desc.bmAttributes; 185250003Sadrian (*config)->MaxPower = pconf->desc.bMaxPower; 186250003Sadrian (*config)->extra_length = pconf->extra.len; 187250003Sadrian if ((*config)->extra_length != 0) 188250003Sadrian (*config)->extra = pconf->extra.ptr; 189250003Sadrian 190250003Sadrian for (i = 0 ; i < nif ; i++) { 191250003Sadrian pinf = &pconf->interface[i]; 192250003Sadrian (*config)->interface[i].num_altsetting = pinf->num_altsetting + 1; 193250003Sadrian for (j = 0 ; j < (*config)->interface[i].num_altsetting ; j++) { 194250003Sadrian if (j != 0) 195250003Sadrian pinf = &pconf->interface[i].altsetting[j - 1]; 196 ifd = &(*config)->interface[i].altsetting[j]; 197 ifd->bLength = pinf->desc.bLength; 198 ifd->bDescriptorType = pinf->desc.bDescriptorType; 199 ifd->bInterfaceNumber = pinf->desc.bInterfaceNumber; 200 ifd->bAlternateSetting = pinf->desc.bAlternateSetting; 201 ifd->bNumEndpoints = pinf->desc.bNumEndpoints; 202 ifd->bInterfaceClass = pinf->desc.bInterfaceClass; 203 ifd->bInterfaceSubClass = pinf->desc.bInterfaceSubClass; 204 ifd->bInterfaceProtocol = pinf->desc.bInterfaceProtocol; 205 ifd->iInterface = pinf->desc.iInterface; 206 ifd->extra_length = pinf->extra.len; 207 if (ifd->extra_length != 0) 208 ifd->extra = pinf->extra.ptr; 209 for (k = 0 ; k < pinf->num_endpoints ; k++) { 210 pend = &pinf->endpoints[k]; 211 endd = &ifd->endpoint[k]; 212 endd->bLength = pend->desc.bLength; 213 endd->bDescriptorType = pend->desc.bDescriptorType; 214 endd->bEndpointAddress = pend->desc.bEndpointAddress; 215 endd->bmAttributes = pend->desc.bmAttributes; 216 endd->wMaxPacketSize = pend->desc.wMaxPacketSize; 217 endd->bInterval = pend->desc.bInterval; 218 endd->bRefresh = pend->desc.bRefresh; 219 endd->bSynchAddress = pend->desc.bSynchAddress; 220 endd->extra_length = pend->extra.len; 221 if (endd->extra_length != 0) 222 endd->extra = pend->extra.ptr; 223 } 224 } 225 } 226 227 free(pconf); 228 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_config_descriptor leave"); 229 return (0); 230} 231 232int 233libusb_get_config_descriptor_by_value(libusb_device * dev, 234 uint8_t bConfigurationValue, struct libusb_config_descriptor **config) 235{ 236 struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 237 struct libusb20_device *pdev; 238 struct libusb20_config *pconf; 239 libusb_context *ctx; 240 int i; 241 242 ctx = NULL; 243 GET_CONTEXT(ctx); 244 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_config_descriptor_by_value enter"); 245 246 if (dev == NULL || config == NULL) 247 return (LIBUSB_ERROR_INVALID_PARAM); 248 249 pdev = dev->os_priv; 250 pdesc = libusb20_dev_get_device_desc(pdev); 251 252 for (i = 0 ; i < pdesc->bNumConfigurations ; i++) { 253 pconf = libusb20_dev_alloc_config(pdev, i); 254 if (pconf->desc.bConfigurationValue == bConfigurationValue) { 255 free(pconf); 256 return libusb_get_config_descriptor(dev, i, config); 257 258 } 259 free(pconf); 260 } 261 262 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_config_descriptor_by_value leave"); 263 return (LIBUSB_ERROR_NOT_FOUND); 264} 265 266void 267libusb_free_config_descriptor(struct libusb_config_descriptor *config) 268{ 269 libusb_context *ctx; 270 271 ctx = NULL; 272 GET_CONTEXT(ctx); 273 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_config_descriptor enter"); 274 275 free(config); 276 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_config_descriptor leave"); 277} 278 279int 280libusb_get_string_descriptor_ascii(libusb_device_handle * dev, 281 uint8_t desc_index, unsigned char *data, int length) 282{ 283 struct libusb20_device *pdev; 284 libusb_context *ctx; 285 int ret; 286 287 ctx = NULL; 288 GET_CONTEXT(ctx); 289 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_string_descriptor_ascii enter"); 290 291 if (dev == NULL || data == NULL) 292 return (LIBUSB20_ERROR_INVALID_PARAM); 293 294 pdev = dev->os_priv; 295 dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_string_descriptor_ascii leave"); 296 if (libusb20_dev_req_string_simple_sync(pdev, desc_index, 297 data, length) == 0) 298 return (strlen(data)); 299 300 return (LIBUSB_ERROR_OTHER); 301} 302