libusb10_desc.c (195560) | libusb10_desc.c (195957) |
---|---|
1/* $FreeBSD: head/lib/libusb/libusb10_desc.c 195560 2009-07-10 14:15:53Z thompsa $ */ | 1/* $FreeBSD: head/lib/libusb/libusb10_desc.c 195957 2009-07-30 00:11:41Z alfred $ */ |
2/*- 3 * Copyright (c) 2009 Sylvestre Gallon. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. --- 9 unchanged lines hidden (view full) --- 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 | 2/*- 3 * Copyright (c) 2009 Sylvestre Gallon. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. --- 9 unchanged lines hidden (view full) --- 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 |
27#include <sys/queue.h> | |
28#include <stdlib.h> 29#include <stdio.h> 30#include <pthread.h> | 27#include <stdlib.h> 28#include <stdio.h> 29#include <pthread.h> |
30#include <sys/queue.h> |
|
31 32#include "libusb20.h" 33#include "libusb20_desc.h" 34#include "libusb20_int.h" 35#include "libusb.h" 36#include "libusb10.h" 37 38/* USB descriptors */ 39 40int | 31 32#include "libusb20.h" 33#include "libusb20_desc.h" 34#include "libusb20_int.h" 35#include "libusb.h" 36#include "libusb10.h" 37 38/* USB descriptors */ 39 40int |
41libusb_get_device_descriptor(libusb_device * dev, | 41libusb_get_device_descriptor(libusb_device *dev, |
42 struct libusb_device_descriptor *desc) 43{ 44 struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 45 struct libusb20_device *pdev; | 42 struct libusb_device_descriptor *desc) 43{ 44 struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 45 struct libusb20_device *pdev; |
46 libusb_context *ctx; | |
47 | 46 |
48 ctx = NULL; 49 GET_CONTEXT(ctx); 50 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_descriptor enter"); 51 | |
52 if ((dev == NULL) || (desc == NULL)) 53 return (LIBUSB_ERROR_INVALID_PARAM); 54 55 pdev = dev->os_priv; 56 pdesc = libusb20_dev_get_device_desc(pdev); 57 58 desc->bLength = pdesc->bLength; 59 desc->bDescriptorType = pdesc->bDescriptorType; --- 5 unchanged lines hidden (view full) --- 65 desc->idVendor = pdesc->idVendor; 66 desc->idProduct = pdesc->idProduct; 67 desc->bcdDevice = pdesc->bcdDevice; 68 desc->iManufacturer = pdesc->iManufacturer; 69 desc->iProduct = pdesc->iProduct; 70 desc->iSerialNumber = pdesc->iSerialNumber; 71 desc->bNumConfigurations = pdesc->bNumConfigurations; 72 | 47 if ((dev == NULL) || (desc == NULL)) 48 return (LIBUSB_ERROR_INVALID_PARAM); 49 50 pdev = dev->os_priv; 51 pdesc = libusb20_dev_get_device_desc(pdev); 52 53 desc->bLength = pdesc->bLength; 54 desc->bDescriptorType = pdesc->bDescriptorType; --- 5 unchanged lines hidden (view full) --- 60 desc->idVendor = pdesc->idVendor; 61 desc->idProduct = pdesc->idProduct; 62 desc->bcdDevice = pdesc->bcdDevice; 63 desc->iManufacturer = pdesc->iManufacturer; 64 desc->iProduct = pdesc->iProduct; 65 desc->iSerialNumber = pdesc->iSerialNumber; 66 desc->bNumConfigurations = pdesc->bNumConfigurations; 67 |
73 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_descriptor leave"); | |
74 return (0); 75} 76 77int | 68 return (0); 69} 70 71int |
78libusb_get_active_config_descriptor(libusb_device * dev, | 72libusb_get_active_config_descriptor(libusb_device *dev, |
79 struct libusb_config_descriptor **config) 80{ 81 struct libusb20_device *pdev; | 73 struct libusb_config_descriptor **config) 74{ 75 struct libusb20_device *pdev; |
82 libusb_context *ctx; 83 uint8_t idx; | 76 uint8_t config_index; |
84 | 77 |
85 ctx = NULL; 86 GET_CONTEXT(ctx); 87 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_active_config_descriptor enter"); 88 | |
89 pdev = dev->os_priv; | 78 pdev = dev->os_priv; |
90 idx = libusb20_dev_get_config_index(pdev); | 79 config_index = libusb20_dev_get_config_index(pdev); |
91 | 80 |
92 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_active_config_descriptor leave"); 93 return (libusb_get_config_descriptor(dev, idx, config)); | 81 return (libusb_get_config_descriptor(dev, config_index, config)); |
94} 95 | 82} 83 |
96/* 97 * XXX Need to check if extra need a dup because 98 * XXX free pconf could free this char * 99 */ | |
100int | 84int |
101libusb_get_config_descriptor(libusb_device * dev, uint8_t config_index, | 85libusb_get_config_descriptor(libusb_device *dev, uint8_t config_index, |
102 struct libusb_config_descriptor **config) 103{ 104 struct libusb20_device *pdev; 105 struct libusb20_config *pconf; 106 struct libusb20_interface *pinf; 107 struct libusb20_endpoint *pend; | 86 struct libusb_config_descriptor **config) 87{ 88 struct libusb20_device *pdev; 89 struct libusb20_config *pconf; 90 struct libusb20_interface *pinf; 91 struct libusb20_endpoint *pend; |
108 libusb_interface_descriptor *ifd; 109 libusb_endpoint_descriptor *endd; 110 libusb_context *ctx; 111 uint8_t nif, nend, nalt, i, j, k; 112 uint32_t if_idx, endp_idx; | 92 struct libusb_config_descriptor *pconfd; 93 struct libusb_interface_descriptor *ifd; 94 struct libusb_endpoint_descriptor *endd; 95 uint8_t *pextra; 96 uint16_t nextra; 97 uint8_t nif; 98 uint8_t nep; 99 uint8_t nalt; 100 uint8_t i; 101 uint8_t j; 102 uint8_t k; |
113 | 103 |
114 ctx = NULL; 115 GET_CONTEXT(ctx); 116 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_config_descriptor enter"); 117 | |
118 if (dev == NULL || config == NULL) 119 return (LIBUSB_ERROR_INVALID_PARAM); 120 | 104 if (dev == NULL || config == NULL) 105 return (LIBUSB_ERROR_INVALID_PARAM); 106 |
107 *config = NULL; 108 |
|
121 pdev = dev->os_priv; 122 pconf = libusb20_dev_alloc_config(pdev, config_index); 123 124 if (pconf == NULL) 125 return (LIBUSB_ERROR_NOT_FOUND); 126 127 nalt = nif = pconf->num_interface; | 109 pdev = dev->os_priv; 110 pconf = libusb20_dev_alloc_config(pdev, config_index); 111 112 if (pconf == NULL) 113 return (LIBUSB_ERROR_NOT_FOUND); 114 115 nalt = nif = pconf->num_interface; |
128 nend = 0; 129 for (i = 0 ; i < nif ; i++) { 130 if (pconf->interface[i].num_altsetting > 0) 131 { 132 nalt += pconf->interface[i].num_altsetting; 133 for (j = 0 ; j < nalt ; j++) { 134 nend += pconf->interface[i].altsetting[j].num_endpoints; | 116 nep = 0; 117 nextra = pconf->extra.len; 118 119 for (i = 0; i < nif; i++) { 120 121 pinf = pconf->interface + i; 122 nextra += pinf->extra.len; 123 nep += pinf->num_endpoints; 124 k = pinf->num_endpoints; 125 pend = pinf->endpoints; 126 while (k--) { 127 nextra += pend->extra.len; 128 pend++; 129 } 130 131 j = pinf->num_altsetting; 132 nalt += pinf->num_altsetting; 133 pinf = pinf->altsetting; 134 while (j--) { 135 nextra += pinf->extra.len; 136 nep += pinf->num_endpoints; 137 k = pinf->num_endpoints; 138 pend = pinf->endpoints; 139 while (k--) { 140 nextra += pend->extra.len; 141 pend++; |
135 } | 142 } |
143 pinf++; |
|
136 } | 144 } |
137 nend += pconf->interface[i].num_endpoints; | |
138 } 139 | 145 } 146 |
140 *config = malloc(sizeof(libusb_config_descriptor) + | 147 nextra = nextra + 148 (1 * sizeof(libusb_config_descriptor)) + |
141 (nif * sizeof(libusb_interface)) + 142 (nalt * sizeof(libusb_interface_descriptor)) + | 149 (nif * sizeof(libusb_interface)) + 150 (nalt * sizeof(libusb_interface_descriptor)) + |
143 (nend * sizeof(libusb_endpoint_descriptor))); 144 if (*config == NULL) { | 151 (nep * sizeof(libusb_endpoint_descriptor)); 152 153 pconfd = malloc(nextra); 154 155 if (pconfd == NULL) { |
145 free(pconf); 146 return (LIBUSB_ERROR_NO_MEM); 147 } | 156 free(pconf); 157 return (LIBUSB_ERROR_NO_MEM); 158 } |
159 /* make sure memory is clean */ 160 memset(pconfd, 0, nextra); |
|
148 | 161 |
149 (*config)->interface = (libusb_interface *)(*config + | 162 pconfd->interface = (libusb_interface *) (pconfd + |
150 sizeof(libusb_config_descriptor)); | 163 sizeof(libusb_config_descriptor)); |
151 for (i = if_idx = endp_idx = 0 ; i < nif ; if_idx, i++) { 152 (*config)->interface[i].altsetting = (libusb_interface_descriptor *) 153 (*config + sizeof(libusb_config_descriptor) + 154 (nif * sizeof(libusb_interface)) + 155 (if_idx * sizeof(libusb_interface_descriptor))); 156 (*config)->interface[i].altsetting[0].endpoint = 157 (libusb_endpoint_descriptor *) (*config + 158 sizeof(libusb_config_descriptor) + 159 (nif * sizeof(libusb_interface)) + 160 (nalt * sizeof(libusb_interface_descriptor)) + 161 (endp_idx * sizeof(libusb_endpoint_descriptor))); 162 endp_idx += pconf->interface[i].num_endpoints; | |
163 | 164 |
164 if (pconf->interface[i].num_altsetting > 0) 165 { 166 for (j = 0 ; j < pconf->interface[i].num_altsetting ; j++, if_idx++) { 167 (*config)->interface[i].altsetting[j + 1].endpoint = 168 (libusb_endpoint_descriptor *) (*config + 169 sizeof(libusb_config_descriptor) + 170 (nif * sizeof(libusb_interface)) + 171 (nalt * sizeof(libusb_interface_descriptor)) + 172 (endp_idx * sizeof(libusb_endpoint_descriptor))); 173 endp_idx += pconf->interface[i].altsetting[j].num_endpoints; 174 } | 165 ifd = (libusb_interface_descriptor *) (pconfd->interface + nif); 166 endd = (libusb_endpoint_descriptor *) (ifd + nalt); 167 pextra = (uint8_t *)(endd + nep); 168 169 /* fill in config descriptor */ 170 171 pconfd->bLength = pconf->desc.bLength; 172 pconfd->bDescriptorType = pconf->desc.bDescriptorType; 173 pconfd->wTotalLength = pconf->desc.wTotalLength; 174 pconfd->bNumInterfaces = pconf->desc.bNumInterfaces; 175 pconfd->bConfigurationValue = pconf->desc.bConfigurationValue; 176 pconfd->iConfiguration = pconf->desc.iConfiguration; 177 pconfd->bmAttributes = pconf->desc.bmAttributes; 178 pconfd->MaxPower = pconf->desc.bMaxPower; 179 180 if (pconf->extra.len != 0) { 181 pconfd->extra_length = pconf->extra.len; 182 pconfd->extra = pextra; 183 memcpy(pextra, pconf->extra.ptr, pconfd->extra_length); 184 pextra += pconfd->extra_length; 185 } 186 /* setup all interface and endpoint pointers */ 187 188 for (i = 0; i < nif; i++) { 189 190 pconfd->interface[i].altsetting = ifd; 191 ifd->endpoint = endd; 192 endd += pconf->interface[i].num_endpoints; 193 ifd++; 194 195 for (j = 0; j < pconf->interface[i].num_altsetting; j++) { 196 ifd->endpoint = endd; 197 endd += pconf->interface[i].altsetting[j].num_endpoints; 198 ifd++; |
175 } 176 } 177 | 199 } 200 } 201 |
178 (*config)->bLength = pconf->desc.bLength; 179 (*config)->bDescriptorType = pconf->desc.bDescriptorType; 180 (*config)->wTotalLength = pconf->desc.wTotalLength; 181 (*config)->bNumInterfaces = pconf->desc.bNumInterfaces; 182 (*config)->bConfigurationValue = pconf->desc.bConfigurationValue; 183 (*config)->iConfiguration = pconf->desc.iConfiguration; 184 (*config)->bmAttributes = pconf->desc.bmAttributes; 185 (*config)->MaxPower = pconf->desc.bMaxPower; 186 (*config)->extra_length = pconf->extra.len; 187 if ((*config)->extra_length != 0) 188 (*config)->extra = pconf->extra.ptr; | 202 /* fill in all interface and endpoint data */ |
189 | 203 |
190 for (i = 0 ; i < nif ; i++) { | 204 for (i = 0; i < nif; i++) { |
191 pinf = &pconf->interface[i]; | 205 pinf = &pconf->interface[i]; |
192 (*config)->interface[i].num_altsetting = pinf->num_altsetting + 1; 193 for (j = 0 ; j < (*config)->interface[i].num_altsetting ; j++) { | 206 pconfd->interface[i].num_altsetting = pinf->num_altsetting + 1; 207 for (j = 0; j < pconfd->interface[i].num_altsetting; j++) { |
194 if (j != 0) 195 pinf = &pconf->interface[i].altsetting[j - 1]; | 208 if (j != 0) 209 pinf = &pconf->interface[i].altsetting[j - 1]; |
196 ifd = &(*config)->interface[i].altsetting[j]; | 210 ifd = &pconfd->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; | 211 ifd->bLength = pinf->desc.bLength; 212 ifd->bDescriptorType = pinf->desc.bDescriptorType; 213 ifd->bInterfaceNumber = pinf->desc.bInterfaceNumber; 214 ifd->bAlternateSetting = pinf->desc.bAlternateSetting; 215 ifd->bNumEndpoints = pinf->desc.bNumEndpoints; 216 ifd->bInterfaceClass = pinf->desc.bInterfaceClass; 217 ifd->bInterfaceSubClass = pinf->desc.bInterfaceSubClass; 218 ifd->bInterfaceProtocol = pinf->desc.bInterfaceProtocol; 219 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++) { | 220 if (pinf->extra.len != 0) { 221 ifd->extra_length = pinf->extra.len; 222 ifd->extra = pextra; 223 memcpy(pextra, pinf->extra.ptr, pinf->extra.len); 224 pextra += pinf->extra.len; 225 } 226 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; | 227 pend = &pinf->endpoints[k]; 228 endd = &ifd->endpoint[k]; 229 endd->bLength = pend->desc.bLength; 230 endd->bDescriptorType = pend->desc.bDescriptorType; 231 endd->bEndpointAddress = pend->desc.bEndpointAddress; 232 endd->bmAttributes = pend->desc.bmAttributes; 233 endd->wMaxPacketSize = pend->desc.wMaxPacketSize; 234 endd->bInterval = pend->desc.bInterval; 235 endd->bRefresh = pend->desc.bRefresh; 236 endd->bSynchAddress = pend->desc.bSynchAddress; |
220 endd->extra_length = pend->extra.len; 221 if (endd->extra_length != 0) 222 endd->extra = pend->extra.ptr; | 237 if (pend->extra.len != 0) { 238 endd->extra_length = pend->extra.len; 239 endd->extra = pextra; 240 memcpy(pextra, pend->extra.ptr, pend->extra.len); 241 pextra += pend->extra.len; 242 } |
223 } | 243 } |
224 } | 244 } |
225 } 226 227 free(pconf); | 245 } 246 247 free(pconf); |
228 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_config_descriptor leave"); 229 return (0); | 248 249 *config = pconfd; 250 251 return (0); /* success */ |
230} 231 232int | 252} 253 254int |
233libusb_get_config_descriptor_by_value(libusb_device * dev, | 255libusb_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; | 256 uint8_t bConfigurationValue, struct libusb_config_descriptor **config) 257{ 258 struct LIBUSB20_DEVICE_DESC_DECODED *pdesc; 259 struct libusb20_device *pdev; |
238 struct libusb20_config *pconf; 239 libusb_context *ctx; | |
240 int i; | 260 int i; |
261 int err; |
|
241 | 262 |
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); | 263 if (dev == NULL || config == NULL) 264 return (LIBUSB_ERROR_INVALID_PARAM); |
248 | 265 |
249 pdev = dev->os_priv; 250 pdesc = libusb20_dev_get_device_desc(pdev); 251 | 266 pdev = dev->os_priv; 267 pdesc = libusb20_dev_get_device_desc(pdev); 268 |
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); | 269 for (i = 0; i < pdesc->bNumConfigurations; i++) { 270 err = libusb_get_config_descriptor(dev, i, config); 271 if (err) 272 return (err); |
257 | 273 |
258 } 259 free(pconf); | 274 if ((*config)->bConfigurationValue == bConfigurationValue) 275 return (0); /* success */ 276 277 libusb_free_config_descriptor(*config); |
260 } 261 | 278 } 279 |
262 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_config_descriptor_by_value leave"); | 280 *config = NULL; 281 |
263 return (LIBUSB_ERROR_NOT_FOUND); 264} 265 266void 267libusb_free_config_descriptor(struct libusb_config_descriptor *config) 268{ | 282 return (LIBUSB_ERROR_NOT_FOUND); 283} 284 285void 286libusb_free_config_descriptor(struct libusb_config_descriptor *config) 287{ |
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); | 288 free(config); |
276 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_config_descriptor leave"); | |
277} 278 279int | 289} 290 291int |
280libusb_get_string_descriptor_ascii(libusb_device_handle * dev, | 292libusb_get_string_descriptor_ascii(libusb_device_handle *pdev, |
281 uint8_t desc_index, unsigned char *data, int length) 282{ | 293 uint8_t desc_index, unsigned char *data, int length) 294{ |
283 struct libusb20_device *pdev; 284 libusb_context *ctx; 285 286 ctx = NULL; 287 GET_CONTEXT(ctx); 288 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_string_descriptor_ascii enter"); 289 290 if (dev == NULL || data == NULL) | 295 if (pdev == NULL || data == NULL || length < 1) |
291 return (LIBUSB20_ERROR_INVALID_PARAM); 292 | 296 return (LIBUSB20_ERROR_INVALID_PARAM); 297 |
293 pdev = dev->os_priv; 294 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_string_descriptor_ascii leave"); 295 if (libusb20_dev_req_string_simple_sync(pdev, desc_index, | 298 /* put some default data into the destination buffer */ 299 data[0] = 0; 300 301 if (libusb20_dev_req_string_simple_sync(pdev, desc_index, |
296 data, length) == 0) 297 return (strlen(data)); 298 299 return (LIBUSB_ERROR_OTHER); 300} | 302 data, length) == 0) 303 return (strlen(data)); 304 305 return (LIBUSB_ERROR_OTHER); 306} |