more error code sanitization
[platform/upstream/libusb.git] / libusb / descriptor.c
1 /*
2  * USB descriptor handling functions for libusb
3  * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
4  * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "libusbi.h"
26
27 #define DESC_HEADER_LENGTH              2
28 #define DEVICE_DESC_LENGTH              18
29 #define CONFIG_DESC_LENGTH              9
30 #define INTERFACE_DESC_LENGTH           9
31 #define ENDPOINT_DESC_LENGTH            7
32 #define ENDPOINT_AUDIO_DESC_LENGTH      9
33
34 /** @defgroup desc USB descriptors
35  * This page details how to examine the various standard USB descriptors
36  * for detected devices
37  */
38
39 int usbi_parse_descriptor(unsigned char *source, char *descriptor, void *dest)
40 {
41         unsigned char *sp = source, *dp = dest;
42         uint16_t w;
43         uint32_t d;
44         char *cp;
45
46         for (cp = descriptor; *cp; cp++) {
47                 switch (*cp) {
48                         case 'b':       /* 8-bit byte */
49                                 *dp++ = *sp++;
50                                 break;
51                         case 'w':       /* 16-bit word, convert from little endian to CPU */
52                                 w = (sp[1] << 8) | sp[0]; sp += 2;
53                                 dp += ((unsigned long)dp & 1);  /* Align to word boundary */
54                                 *((uint16_t *)dp) = w; dp += 2;
55                                 break;
56                         case 'd':       /* 32-bit dword, convert from little endian to CPU */
57                                 d = (sp[3] << 24) | (sp[2] << 16) | (sp[1] << 8) | sp[0]; sp += 4;
58                                 dp += ((unsigned long)dp & 2);  /* Align to dword boundary */
59                                 *((uint32_t *)dp) = d; dp += 4;
60                                 break;
61                         case 'W':       /* 16-bit word, keep CPU endianess */
62                                 dp += ((unsigned long)dp & 1);  /* Align to word boundary */
63                                 memcpy(dp, sp, 2); sp += 2; dp += 2;
64                                 break;
65                         case 'D':       /* 32-bit dword, keep CPU endianess */
66                                 dp += ((unsigned long)dp & 2);  /* Align to dword boundary */
67                                 memcpy(dp, sp, 4); sp += 4; dp += 4;
68                                 break;
69                 }
70         }
71
72         return sp - source;
73 }
74
75 static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint)
76 {
77         if (endpoint->extra)
78                 free((unsigned char *) endpoint->extra);
79 }
80
81 static int parse_endpoint(struct libusb_endpoint_descriptor *endpoint,
82         unsigned char *buffer, int size)
83 {
84         struct usb_descriptor_header header;
85         unsigned char *extra;
86         unsigned char *begin;
87         int parsed = 0;
88         int len;
89
90         usbi_parse_descriptor(buffer, "bb", &header);
91
92         /* Everything should be fine being passed into here, but we sanity */
93         /*  check JIC */
94         if (header.bLength > size) {
95                 usbi_err("ran out of descriptors parsing");
96                 return -1;
97         }
98
99         if (header.bDescriptorType != LIBUSB_DT_ENDPOINT) {
100                 usbi_err("unexpected descriptor %x (expected %x)",
101                         header.bDescriptorType, LIBUSB_DT_ENDPOINT);
102                 return parsed;
103         }
104
105         if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH)
106                 usbi_parse_descriptor(buffer, "bbbbwbbb", endpoint);
107         else if (header.bLength >= ENDPOINT_DESC_LENGTH)
108                 usbi_parse_descriptor(buffer, "bbbbwb", endpoint);
109
110         buffer += header.bLength;
111         size -= header.bLength;
112         parsed += header.bLength;
113
114         /* Skip over the rest of the Class Specific or Vendor Specific */
115         /*  descriptors */
116         begin = buffer;
117         while (size >= DESC_HEADER_LENGTH) {
118                 usbi_parse_descriptor(buffer, "bb", &header);
119
120                 if (header.bLength < 2) {
121                         usbi_err("invalid descriptor length %d", header.bLength);
122                         return -1;
123                 }
124
125                 /* If we find another "proper" descriptor then we're done  */
126                 if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
127                                 (header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
128                                 (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
129                                 (header.bDescriptorType == LIBUSB_DT_DEVICE))
130                         break;
131
132                 usbi_dbg("skipping descriptor %x", header.bDescriptorType);
133                 buffer += header.bLength;
134                 size -= header.bLength;
135                 parsed += header.bLength;
136         }
137
138         /* Copy any unknown descriptors into a storage area for drivers */
139         /*  to later parse */
140         len = (int)(buffer - begin);
141         if (!len) {
142                 endpoint->extra = NULL;
143                 endpoint->extralen = 0;
144                 return parsed;
145         }
146
147         extra = malloc(len);
148         endpoint->extra = extra;
149         if (!extra) {
150                 endpoint->extralen = 0;
151                 return LIBUSB_ERROR_NO_MEM;
152         }
153
154         memcpy(extra, begin, len);
155         endpoint->extralen = len;
156
157         return parsed;
158 }
159
160 static void clear_interface(struct libusb_interface *interface)
161 {
162         int i;
163         int j;
164
165         if (interface->altsetting) {
166                 for (i = 0; i < interface->num_altsetting; i++) {
167                         struct libusb_interface_descriptor *ifp =
168                                 (struct libusb_interface_descriptor *)
169                                 interface->altsetting + i;
170                         if (ifp->extra)
171                                 free((void *) ifp->extra);
172                         if (ifp->endpoint) {
173                                 for (j = 0; j < ifp->bNumEndpoints; j++)
174                                         clear_endpoint((struct libusb_endpoint_descriptor *)
175                                                 ifp->endpoint + j);
176                                 free((void *) ifp->endpoint);
177                         }
178                 }
179                 free((void *) interface->altsetting);
180         }
181         
182 }
183
184 static int parse_interface(struct libusb_interface *interface,
185         unsigned char *buffer, int size)
186 {
187         int i;
188         int len;
189         int r;
190         int parsed = 0;
191         int tmp;
192         struct usb_descriptor_header header;
193         struct libusb_interface_descriptor *ifp;
194         unsigned char *begin;
195
196         interface->num_altsetting = 0;
197
198         while (size >= INTERFACE_DESC_LENGTH) {
199                 struct libusb_interface_descriptor *altsetting =
200                         (struct libusb_interface_descriptor *) interface->altsetting;
201                 altsetting = realloc(altsetting,
202                         sizeof(struct libusb_interface_descriptor) *
203                         (interface->num_altsetting + 1));
204                 if (!altsetting) {
205                         r = LIBUSB_ERROR_NO_MEM;
206                         goto err;
207                 }
208                 interface->altsetting = altsetting;
209
210                 ifp = altsetting + interface->num_altsetting;
211                 interface->num_altsetting++;
212                 usbi_parse_descriptor(buffer, "bbbbbbbbb", ifp);
213                 ifp->extra = NULL;
214                 ifp->extralen = 0;
215                 ifp->endpoint = NULL;
216
217                 /* Skip over the interface */
218                 buffer += ifp->bLength;
219                 parsed += ifp->bLength;
220                 size -= ifp->bLength;
221
222                 begin = buffer;
223
224                 /* Skip over any interface, class or vendor descriptors */
225                 while (size >= DESC_HEADER_LENGTH) {
226                         usbi_parse_descriptor(buffer, "bb", &header);
227                         if (header.bLength < 2) {
228                                 usbi_err("invalid descriptor of length %d", header.bLength);
229                                 r = LIBUSB_ERROR_IO;
230                                 goto err;
231                         }
232
233                         /* If we find another "proper" descriptor then we're done */
234                         if ((header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
235                                         (header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
236                                         (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
237                                         (header.bDescriptorType == LIBUSB_DT_DEVICE))
238                                 break;
239
240                         buffer += header.bLength;
241                         parsed += header.bLength;
242                         size -= header.bLength;
243                 }
244
245                 /* Copy any unknown descriptors into a storage area for */
246                 /*  drivers to later parse */
247                 len = (int)(buffer - begin);
248                 if (len) {
249                         ifp->extra = malloc(len);
250                         if (!ifp->extra) {
251                                 r = LIBUSB_ERROR_NO_MEM;
252                                 goto err;
253                         }
254                         memcpy((unsigned char *) ifp->extra, begin, len);
255                         ifp->extralen = len;
256                 }
257
258                 /* Did we hit an unexpected descriptor? */
259                 usbi_parse_descriptor(buffer, "bb", &header);
260                 if ((size >= DESC_HEADER_LENGTH) &&
261                                 ((header.bDescriptorType == LIBUSB_DT_CONFIG) ||
262                                  (header.bDescriptorType == LIBUSB_DT_DEVICE)))
263                         return parsed;
264
265                 if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
266                         usbi_err("too many endpoints (%d)", ifp->bNumEndpoints);
267                         r = LIBUSB_ERROR_IO;
268                         goto err;
269                 }
270
271                 if (ifp->bNumEndpoints > 0) {
272                         struct libusb_endpoint_descriptor *endpoint;
273                         tmp = ifp->bNumEndpoints * sizeof(struct libusb_endpoint_descriptor);
274                         endpoint = malloc(tmp);
275                         ifp->endpoint = endpoint;
276                         if (!endpoint) {
277                                 r = LIBUSB_ERROR_NO_MEM;
278                                 goto err;
279                         }
280
281                         memset(endpoint, 0, tmp);
282                         for (i = 0; i < ifp->bNumEndpoints; i++) {
283                                 usbi_parse_descriptor(buffer, "bb", &header);
284
285                                 if (header.bLength > size) {
286                                         usbi_err("ran out of descriptors parsing");
287                                         r = LIBUSB_ERROR_IO;
288                                         goto err;
289                                 }
290
291                                 r = parse_endpoint(endpoint + i, buffer, size);
292                                 if (r < 0)
293                                         goto err;
294
295                                 buffer += r;
296                                 parsed += r;
297                                 size -= r;
298                         }
299                 }
300
301                 /* We check to see if it's an alternate to this one */
302                 ifp = (struct libusb_interface_descriptor *) buffer;
303                 if (size < LIBUSB_DT_INTERFACE_SIZE ||
304                                 ifp->bDescriptorType != LIBUSB_DT_INTERFACE ||
305                                 !ifp->bAlternateSetting)
306                         return parsed;
307         }
308
309         return parsed;
310 err:
311         clear_interface(interface);
312         return r;
313 }
314
315 static void clear_configuration(struct libusb_config_descriptor *config)
316 {
317         if (config->interface) {
318                 int i;
319                 for (i = 0; i < config->bNumInterfaces; i++)
320                         clear_interface((struct libusb_interface *)
321                                 config->interface + i);
322                 free((void *) config->interface);
323         }
324         if (config->extra)
325                 free((void *) config->extra);
326 }
327
328 void usbi_clear_configurations(struct libusb_device *dev)
329 {
330         int i;
331         for (i = 0; i < dev->desc.bNumConfigurations; i++)
332                 clear_configuration(dev->config + i);
333 }
334
335 int usbi_parse_configuration(struct libusb_config_descriptor *config,
336         unsigned char *buffer)
337 {
338         int i;
339         int r;
340         int size;
341         int tmp;
342         struct usb_descriptor_header header;
343         struct libusb_interface *interface;
344
345         usbi_parse_descriptor(buffer, "bbwbbbbb", config);
346         size = config->wTotalLength;
347
348         if (config->bNumInterfaces > USB_MAXINTERFACES) {
349                 usbi_err("too many interfaces (%d)", config->bNumInterfaces);
350                 return LIBUSB_ERROR_IO;
351         }
352
353         tmp = config->bNumInterfaces * sizeof(struct libusb_interface);
354         interface = malloc(tmp);
355         config->interface = interface;
356         if (!config->interface)
357                 return LIBUSB_ERROR_NO_MEM;
358
359         memset(interface, 0, tmp);
360         buffer += config->bLength;
361         size -= config->bLength;
362
363         config->extra = NULL;
364         config->extralen = 0;
365
366         for (i = 0; i < config->bNumInterfaces; i++) {
367                 int len;
368                 unsigned char *begin;
369
370                 /* Skip over the rest of the Class Specific or Vendor */
371                 /*  Specific descriptors */
372                 begin = buffer;
373                 while (size >= DESC_HEADER_LENGTH) {
374                         usbi_parse_descriptor(buffer, "bb", &header);
375
376                         if ((header.bLength > size) ||
377                                         (header.bLength < DESC_HEADER_LENGTH)) {
378                                 usbi_err("invalid descriptor length of %d", header.bLength);
379                                 r = LIBUSB_ERROR_IO;
380                                 goto err;
381                         }
382
383                         /* If we find another "proper" descriptor then we're done */
384                         if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
385                                         (header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
386                                         (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
387                                         (header.bDescriptorType == LIBUSB_DT_DEVICE))
388                                 break;
389
390                         usbi_dbg("skipping descriptor 0x%x\n", header.bDescriptorType);
391                         buffer += header.bLength;
392                         size -= header.bLength;
393                 }
394
395                 /* Copy any unknown descriptors into a storage area for */
396                 /*  drivers to later parse */
397                 len = (int)(buffer - begin);
398                 if (len) {
399                         /* FIXME: We should realloc and append here */
400                         if (!config->extralen) {
401                                 config->extra = malloc(len);
402                                 if (!config->extra) {
403                                         r = LIBUSB_ERROR_NO_MEM;
404                                         goto err;
405                                 }
406
407                                 memcpy((unsigned char *) config->extra, begin, len);
408                                 config->extralen = len;
409                         }
410                 }
411
412                 r = parse_interface(interface + i, buffer, size);
413                 if (r < 0)
414                         goto err;
415
416                 buffer += r;
417                 size -= r;
418         }
419
420         return size;
421
422 err:
423         clear_configuration(config);
424         return r;
425 }
426
427 /** \ingroup desc
428  * Get the USB device descriptor for a given device.
429  * \param dev the device
430  * \returns the USB device descriptor
431  */
432 API_EXPORTED const struct libusb_device_descriptor *libusb_get_device_descriptor(
433         libusb_device *dev)
434 {
435         return &dev->desc;
436 }
437
438 /** \ingroup desc
439  * Get the USB configuration descriptor for a given device.
440  * \param dev the device
441  * \returns the USB configuration descriptor
442  */
443 API_EXPORTED const struct libusb_config_descriptor *libusb_get_config_descriptor(
444         libusb_device *dev)
445 {
446         return dev->config;
447 }
448
449 /** \ingroup desc
450  * Retrieve a string descriptor in C style ASCII.
451  *
452  * Wrapper around libusb_get_string_descriptor(). Uses the first language 
453  * supported by the device.
454  *
455  * \param dev a device handle
456  * \param desc_index the index of the descriptor to retrieve
457  * \param data output buffer for ASCII string descriptor
458  * \param length size of data buffer
459  * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
460  */
461 API_EXPORTED int libusb_get_string_descriptor_ascii(libusb_device_handle *dev,
462         uint8_t desc_index, unsigned char *data, int length)
463 {
464         unsigned char tbuf[255]; /* Some devices choke on size > 255 */
465         int r, langid, si, di;
466
467         /* Asking for the zero'th index is special - it returns a string
468          * descriptor that contains all the language IDs supported by the device.
469          * Typically there aren't many - often only one. The language IDs are 16
470          * bit numbers, and they start at the third byte in the descriptor. See
471          * USB 2.0 specification section 9.6.7 for more information. */
472         r = libusb_get_string_descriptor(dev, 0, 0, tbuf, sizeof(tbuf));
473         if (r < 0)
474                 return r;
475
476         if (r < 4)
477                 return LIBUSB_ERROR_IO;
478
479         langid = tbuf[2] | (tbuf[3] << 8);
480
481         r = libusb_get_string_descriptor(dev, desc_index, langid, tbuf,
482                 sizeof(tbuf));
483         if (r < 0)
484                 return r;
485
486         if (tbuf[1] != LIBUSB_DT_STRING)
487                 return LIBUSB_ERROR_IO;
488
489         if (tbuf[0] > r)
490                 return LIBUSB_ERROR_IO;
491
492         for (di = 0, si = 2; si < tbuf[0]; si += 2) {
493                 if (di >= (length - 1))
494                         break;
495
496                 if (tbuf[si + 1]) /* high byte */
497                         data[di++] = '?';
498                 else
499                         data[di++] = tbuf[si];
500         }
501
502         data[di] = 0;
503         return di;
504 }
505