Coverage Report

Created: 2025-02-03 06:23

/src/libusb/libusb/descriptor.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
2
/*
3
 * USB descriptor handling functions for libusb
4
 * Copyright © 2007 Daniel Drake <dsd@gentoo.org>
5
 * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
#include "libusbi.h"
23
24
#include <string.h>
25
26
0
#define DESC_HEADER_LENGTH  2
27
28
/** @defgroup libusb_desc USB descriptors
29
 * This page details how to examine the various standard USB descriptors
30
 * for detected devices
31
 */
32
33
static inline uint16_t ReadLittleEndian16(const uint8_t p[2])
34
0
{
35
0
  return (uint16_t)((uint16_t)p[1] << 8 |
36
0
        (uint16_t)p[0]);
37
0
}
38
39
static inline uint32_t ReadLittleEndian32(const uint8_t p[4])
40
0
{
41
0
  return (uint32_t)((uint32_t)p[3] << 24 |
42
0
        (uint32_t)p[2] << 16 |
43
0
        (uint32_t)p[1] << 8 |
44
0
        (uint32_t)p[0]);
45
0
}
46
47
static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint)
48
0
{
49
0
  free((void *)endpoint->extra);
50
0
}
51
52
static int parse_endpoint(struct libusb_context *ctx,
53
  struct libusb_endpoint_descriptor *endpoint, const uint8_t *buffer, int size)
54
0
{
55
0
  const struct usbi_descriptor_header *header;
56
0
  const uint8_t *begin;
57
0
  void *extra;
58
0
  int parsed = 0;
59
60
0
  if (size < DESC_HEADER_LENGTH) {
61
0
    usbi_err(ctx, "short endpoint descriptor read %d/%d",
62
0
       size, DESC_HEADER_LENGTH);
63
0
    return LIBUSB_ERROR_IO;
64
0
  }
65
66
0
  header = (const struct usbi_descriptor_header *)buffer;
67
0
  if (header->bDescriptorType != LIBUSB_DT_ENDPOINT) {
68
0
    usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
69
0
      header->bDescriptorType, LIBUSB_DT_ENDPOINT);
70
0
    return parsed;
71
0
  } else if (header->bLength < LIBUSB_DT_ENDPOINT_SIZE) {
72
0
    usbi_err(ctx, "invalid endpoint bLength (%u)", header->bLength);
73
0
    return LIBUSB_ERROR_IO;
74
0
  } else if (header->bLength > size) {
75
0
    usbi_warn(ctx, "short endpoint descriptor read %d/%u",
76
0
        size, header->bLength);
77
0
    return parsed;
78
0
  }
79
80
0
  endpoint->bLength = buffer[0];
81
0
  endpoint->bDescriptorType = buffer[1];
82
0
  endpoint->bEndpointAddress = buffer[2];
83
0
  endpoint->bmAttributes = buffer[3];
84
0
  endpoint->wMaxPacketSize = ReadLittleEndian16(&buffer[4]);
85
0
  endpoint->bInterval = buffer[6];
86
0
  if (header->bLength >= LIBUSB_DT_ENDPOINT_AUDIO_SIZE) {
87
0
    endpoint->bRefresh = buffer[7];
88
0
    endpoint->bSynchAddress = buffer[8];
89
0
  }
90
91
0
  buffer += header->bLength;
92
0
  size -= header->bLength;
93
0
  parsed += header->bLength;
94
95
  /* Skip over the rest of the Class Specific or Vendor Specific */
96
  /*  descriptors */
97
0
  begin = buffer;
98
0
  while (size >= DESC_HEADER_LENGTH) {
99
0
    header = (const struct usbi_descriptor_header *)buffer;
100
0
    if (header->bLength < DESC_HEADER_LENGTH) {
101
0
      usbi_err(ctx, "invalid extra ep desc len (%u)",
102
0
         header->bLength);
103
0
      return LIBUSB_ERROR_IO;
104
0
    } else if (header->bLength > size) {
105
0
      usbi_warn(ctx, "short extra ep desc read %d/%u",
106
0
          size, header->bLength);
107
0
      return parsed;
108
0
    }
109
110
    /* If we find another "proper" descriptor then we're done  */
111
0
    if (header->bDescriptorType == LIBUSB_DT_ENDPOINT ||
112
0
        header->bDescriptorType == LIBUSB_DT_INTERFACE ||
113
0
        header->bDescriptorType == LIBUSB_DT_CONFIG ||
114
0
        header->bDescriptorType == LIBUSB_DT_DEVICE)
115
0
      break;
116
117
0
    usbi_dbg(ctx, "skipping descriptor 0x%x", header->bDescriptorType);
118
0
    buffer += header->bLength;
119
0
    size -= header->bLength;
120
0
    parsed += header->bLength;
121
0
  }
122
123
  /* Copy any unknown descriptors into a storage area for drivers */
124
  /*  to later parse */
125
0
  ptrdiff_t len = buffer - begin;
126
0
  if (len <= 0)
127
0
    return parsed;
128
129
0
  extra = malloc((size_t)len);
130
0
  if (!extra)
131
0
    return LIBUSB_ERROR_NO_MEM;
132
133
0
  memcpy(extra, begin, (size_t)len);
134
0
  endpoint->extra = extra;
135
0
  endpoint->extra_length = (int)len;
136
137
0
  return parsed;
138
0
}
139
140
static void clear_interface(struct libusb_interface *usb_interface)
141
0
{
142
0
  int i;
143
144
0
  if (usb_interface->altsetting) {
145
0
    for (i = 0; i < usb_interface->num_altsetting; i++) {
146
0
      struct libusb_interface_descriptor *ifp =
147
0
        (struct libusb_interface_descriptor *)
148
0
        usb_interface->altsetting + i;
149
150
0
      free((void *)ifp->extra);
151
0
      if (ifp->endpoint) {
152
0
        uint8_t j;
153
154
0
        for (j = 0; j < ifp->bNumEndpoints; j++)
155
0
          clear_endpoint((struct libusb_endpoint_descriptor *)
156
0
                   ifp->endpoint + j);
157
0
      }
158
0
      free((void *)ifp->endpoint);
159
0
    }
160
0
  }
161
0
  free((void *)usb_interface->altsetting);
162
0
  usb_interface->altsetting = NULL;
163
0
}
164
165
static int parse_interface(libusb_context *ctx,
166
  struct libusb_interface *usb_interface, const uint8_t *buffer, int size)
167
0
{
168
0
  int r;
169
0
  int parsed = 0;
170
0
  int interface_number = -1;
171
0
  const struct usbi_descriptor_header *header;
172
0
  const struct usbi_interface_descriptor *if_desc;
173
0
  struct libusb_interface_descriptor *ifp;
174
0
  const uint8_t *begin;
175
176
0
  while (size >= LIBUSB_DT_INTERFACE_SIZE) {
177
0
    struct libusb_interface_descriptor *altsetting;
178
179
0
    altsetting = realloc((void *)usb_interface->altsetting,
180
0
      sizeof(*altsetting) * (size_t)(usb_interface->num_altsetting + 1));
181
0
    if (!altsetting) {
182
0
      r = LIBUSB_ERROR_NO_MEM;
183
0
      goto err;
184
0
    }
185
0
    usb_interface->altsetting = altsetting;
186
187
0
    ifp = altsetting + usb_interface->num_altsetting;
188
0
    ifp->bLength = buffer[0];
189
0
    ifp->bDescriptorType = buffer[1];
190
0
    ifp->bInterfaceNumber = buffer[2];
191
0
    ifp->bAlternateSetting = buffer[3];
192
0
    ifp->bNumEndpoints = buffer[4];
193
0
    ifp->bInterfaceClass = buffer[5];
194
0
    ifp->bInterfaceSubClass = buffer[6];
195
0
    ifp->bInterfaceProtocol = buffer[7];
196
0
    ifp->iInterface = buffer[8];
197
0
    if (ifp->bDescriptorType != LIBUSB_DT_INTERFACE) {
198
0
      usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
199
0
         ifp->bDescriptorType, LIBUSB_DT_INTERFACE);
200
0
      return parsed;
201
0
    } else if (ifp->bLength < LIBUSB_DT_INTERFACE_SIZE) {
202
0
      usbi_err(ctx, "invalid interface bLength (%u)",
203
0
         ifp->bLength);
204
0
      r = LIBUSB_ERROR_IO;
205
0
      goto err;
206
0
    } else if (ifp->bLength > size) {
207
0
      usbi_warn(ctx, "short intf descriptor read %d/%u",
208
0
         size, ifp->bLength);
209
0
      return parsed;
210
0
    } else if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
211
0
      usbi_err(ctx, "too many endpoints (%u)", ifp->bNumEndpoints);
212
0
      r = LIBUSB_ERROR_IO;
213
0
      goto err;
214
0
    }
215
216
0
    usb_interface->num_altsetting++;
217
0
    ifp->extra = NULL;
218
0
    ifp->extra_length = 0;
219
0
    ifp->endpoint = NULL;
220
221
0
    if (interface_number == -1)
222
0
      interface_number = ifp->bInterfaceNumber;
223
224
    /* Skip over the interface */
225
0
    buffer += ifp->bLength;
226
0
    parsed += ifp->bLength;
227
0
    size -= ifp->bLength;
228
229
0
    begin = buffer;
230
231
    /* Skip over any interface, class or vendor descriptors */
232
0
    while (size >= DESC_HEADER_LENGTH) {
233
0
      header = (const struct usbi_descriptor_header *)buffer;
234
0
      if (header->bLength < DESC_HEADER_LENGTH) {
235
0
        usbi_err(ctx,
236
0
           "invalid extra intf desc len (%u)",
237
0
           header->bLength);
238
0
        r = LIBUSB_ERROR_IO;
239
0
        goto err;
240
0
      } else if (header->bLength > size) {
241
0
        usbi_warn(ctx,
242
0
            "short extra intf desc read %d/%u",
243
0
            size, header->bLength);
244
0
        return parsed;
245
0
      }
246
247
      /* If we find another "proper" descriptor then we're done */
248
0
      if (header->bDescriptorType == LIBUSB_DT_INTERFACE ||
249
0
          header->bDescriptorType == LIBUSB_DT_ENDPOINT ||
250
0
          header->bDescriptorType == LIBUSB_DT_CONFIG ||
251
0
          header->bDescriptorType == LIBUSB_DT_DEVICE)
252
0
        break;
253
254
0
      buffer += header->bLength;
255
0
      parsed += header->bLength;
256
0
      size -= header->bLength;
257
0
    }
258
259
    /* Copy any unknown descriptors into a storage area for */
260
    /*  drivers to later parse */
261
0
    ptrdiff_t len = buffer - begin;
262
0
    if (len > 0) {
263
0
      void *extra = malloc((size_t)len);
264
265
0
      if (!extra) {
266
0
        r = LIBUSB_ERROR_NO_MEM;
267
0
        goto err;
268
0
      }
269
270
0
      memcpy(extra, begin, (size_t)len);
271
0
      ifp->extra = extra;
272
0
      ifp->extra_length = (int)len;
273
0
    }
274
275
0
    if (ifp->bNumEndpoints > 0) {
276
0
      struct libusb_endpoint_descriptor *endpoint;
277
0
      uint8_t i;
278
279
0
      endpoint = calloc(ifp->bNumEndpoints, sizeof(*endpoint));
280
0
      if (!endpoint) {
281
0
        r = LIBUSB_ERROR_NO_MEM;
282
0
        goto err;
283
0
      }
284
285
0
      ifp->endpoint = endpoint;
286
0
      for (i = 0; i < ifp->bNumEndpoints; i++) {
287
0
        r = parse_endpoint(ctx, endpoint + i, buffer, size);
288
0
        if (r < 0)
289
0
          goto err;
290
0
        if (r == 0) {
291
0
          ifp->bNumEndpoints = i;
292
0
          break;
293
0
        }
294
295
0
        buffer += r;
296
0
        parsed += r;
297
0
        size -= r;
298
0
      }
299
0
    }
300
301
    /* We check to see if it's an alternate to this one */
302
0
    if_desc = (const struct usbi_interface_descriptor *)buffer;
303
0
    if (size < LIBUSB_DT_INTERFACE_SIZE ||
304
0
        if_desc->bDescriptorType != LIBUSB_DT_INTERFACE ||
305
0
        if_desc->bInterfaceNumber != interface_number)
306
0
      return parsed;
307
0
  }
308
309
0
  return parsed;
310
0
err:
311
0
  clear_interface(usb_interface);
312
0
  return r;
313
0
}
314
315
static void clear_configuration(struct libusb_config_descriptor *config)
316
0
{
317
0
  uint8_t i;
318
319
0
  if (config->interface) {
320
0
    for (i = 0; i < config->bNumInterfaces; i++)
321
0
      clear_interface((struct libusb_interface *)
322
0
          config->interface + i);
323
0
  }
324
0
  free((void *)config->interface);
325
0
  free((void *)config->extra);
326
0
}
327
328
static int parse_configuration(struct libusb_context *ctx,
329
  struct libusb_config_descriptor *config, const uint8_t *buffer, int size)
330
0
{
331
0
  uint8_t i;
332
0
  int r;
333
0
  const struct usbi_descriptor_header *header;
334
0
  struct libusb_interface *usb_interface;
335
336
0
  if (size < LIBUSB_DT_CONFIG_SIZE) {
337
0
    usbi_err(ctx, "short config descriptor read %d/%d",
338
0
       size, LIBUSB_DT_CONFIG_SIZE);
339
0
    return LIBUSB_ERROR_IO;
340
0
  }
341
342
0
  config->bLength = buffer[0];
343
0
  config->bDescriptorType = buffer[1];
344
0
  config->wTotalLength = ReadLittleEndian16(&buffer[2]);
345
0
  config->bNumInterfaces = buffer[4];
346
0
  config->bConfigurationValue = buffer[5];
347
0
  config->iConfiguration = buffer[6];
348
0
  config->bmAttributes = buffer[7];
349
0
  config->MaxPower = buffer[8];
350
0
  if (config->bDescriptorType != LIBUSB_DT_CONFIG) {
351
0
    usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
352
0
       config->bDescriptorType, LIBUSB_DT_CONFIG);
353
0
    return LIBUSB_ERROR_IO;
354
0
  } else if (config->bLength < LIBUSB_DT_CONFIG_SIZE) {
355
0
    usbi_err(ctx, "invalid config bLength (%u)", config->bLength);
356
0
    return LIBUSB_ERROR_IO;
357
0
  } else if (config->bLength > size) {
358
0
    usbi_err(ctx, "short config descriptor read %d/%u",
359
0
       size, config->bLength);
360
0
    return LIBUSB_ERROR_IO;
361
0
  } else if (config->bNumInterfaces > USB_MAXINTERFACES) {
362
0
    usbi_err(ctx, "too many interfaces (%u)", config->bNumInterfaces);
363
0
    return LIBUSB_ERROR_IO;
364
0
  }
365
366
0
  usb_interface = calloc(config->bNumInterfaces, sizeof(*usb_interface));
367
0
  if (!usb_interface)
368
0
    return LIBUSB_ERROR_NO_MEM;
369
370
0
  config->interface = usb_interface;
371
372
0
  buffer += config->bLength;
373
0
  size -= config->bLength;
374
375
0
  for (i = 0; i < config->bNumInterfaces; i++) {
376
0
    const uint8_t *begin;
377
378
    /* Skip over the rest of the Class Specific or Vendor */
379
    /*  Specific descriptors */
380
0
    begin = buffer;
381
0
    while (size >= DESC_HEADER_LENGTH) {
382
0
      header = (const struct usbi_descriptor_header *)buffer;
383
0
      if (header->bLength < DESC_HEADER_LENGTH) {
384
0
        usbi_err(ctx,
385
0
           "invalid extra config desc len (%u)",
386
0
           header->bLength);
387
0
        r = LIBUSB_ERROR_IO;
388
0
        goto err;
389
0
      } else if (header->bLength > size) {
390
0
        usbi_warn(ctx,
391
0
            "short extra config desc read %d/%u",
392
0
            size, header->bLength);
393
0
        config->bNumInterfaces = i;
394
0
        return size;
395
0
      }
396
397
      /* If we find another "proper" descriptor then we're done */
398
0
      if (header->bDescriptorType == LIBUSB_DT_ENDPOINT ||
399
0
          header->bDescriptorType == LIBUSB_DT_INTERFACE ||
400
0
          header->bDescriptorType == LIBUSB_DT_CONFIG ||
401
0
          header->bDescriptorType == LIBUSB_DT_DEVICE)
402
0
        break;
403
404
0
      usbi_dbg(ctx, "skipping descriptor 0x%x", header->bDescriptorType);
405
0
      buffer += header->bLength;
406
0
      size -= header->bLength;
407
0
    }
408
409
    /* Copy any unknown descriptors into a storage area for */
410
    /*  drivers to later parse */
411
0
    ptrdiff_t len = buffer - begin;
412
0
    if (len > 0) {
413
0
      uint8_t *extra = realloc((void *)config->extra,
414
0
             (size_t)(config->extra_length) + (size_t)len);
415
416
0
      if (!extra) {
417
0
        r = LIBUSB_ERROR_NO_MEM;
418
0
        goto err;
419
0
      }
420
421
0
      memcpy(extra + config->extra_length, begin, (size_t)len);
422
0
      config->extra = extra;
423
0
      config->extra_length += (int)len;
424
0
    }
425
426
0
    r = parse_interface(ctx, usb_interface + i, buffer, (int)size);
427
0
    if (r < 0)
428
0
      goto err;
429
0
    if (r == 0) {
430
0
      config->bNumInterfaces = i;
431
0
      break;
432
0
    }
433
434
0
    buffer += r;
435
0
    size -= r;
436
0
  }
437
438
0
  return size;
439
440
0
err:
441
0
  clear_configuration(config);
442
0
  return r;
443
0
}
444
445
static int raw_desc_to_config(struct libusb_context *ctx,
446
  const uint8_t *buf, int size, struct libusb_config_descriptor **config)
447
0
{
448
0
  struct libusb_config_descriptor *_config = calloc(1, sizeof(*_config));
449
0
  int r;
450
451
0
  if (!_config)
452
0
    return LIBUSB_ERROR_NO_MEM;
453
454
0
  r = parse_configuration(ctx, _config, buf, size);
455
0
  if (r < 0) {
456
0
    usbi_err(ctx, "parse_configuration failed with error %d", r);
457
0
    free(_config);
458
0
    return r;
459
0
  } else if (r > 0) {
460
0
    usbi_warn(ctx, "still %d bytes of descriptor data left", r);
461
0
  }
462
463
0
  *config = _config;
464
0
  return LIBUSB_SUCCESS;
465
0
}
466
467
static int get_active_config_descriptor(struct libusb_device *dev,
468
  uint8_t *buffer, size_t size)
469
0
{
470
0
  int r = usbi_backend.get_active_config_descriptor(dev, buffer, size);
471
472
0
  if (r < 0)
473
0
    return r;
474
475
0
  if (r < LIBUSB_DT_CONFIG_SIZE) {
476
0
    usbi_err(DEVICE_CTX(dev), "short config descriptor read %d/%d",
477
0
       r, LIBUSB_DT_CONFIG_SIZE);
478
0
    return LIBUSB_ERROR_IO;
479
0
  } else if (r != (int)size) {
480
0
    usbi_warn(DEVICE_CTX(dev), "short config descriptor read %d/%d",
481
0
       r, (int)size);
482
0
  }
483
484
0
  return r;
485
0
}
486
487
static int get_config_descriptor(struct libusb_device *dev, uint8_t config_idx,
488
  uint8_t *buffer, size_t size)
489
0
{
490
0
  int r = usbi_backend.get_config_descriptor(dev, config_idx, buffer, size);
491
492
0
  if (r < 0)
493
0
    return r;
494
0
  if (r < LIBUSB_DT_CONFIG_SIZE) {
495
0
    usbi_err(DEVICE_CTX(dev), "short config descriptor read %d/%d",
496
0
       r, LIBUSB_DT_CONFIG_SIZE);
497
0
    return LIBUSB_ERROR_IO;
498
0
  } else if (r != (int)size) {
499
0
    usbi_warn(DEVICE_CTX(dev), "short config descriptor read %d/%d",
500
0
       r, (int)size);
501
0
  }
502
503
0
  return r;
504
0
}
505
506
/** \ingroup libusb_desc
507
 * Get the USB device descriptor for a given device.
508
 *
509
 * This is a non-blocking function; the device descriptor is cached in memory.
510
 *
511
 * Note since libusb-1.0.16, \ref LIBUSBX_API_VERSION >= 0x01000102, this
512
 * function always succeeds.
513
 *
514
 * \param dev the device
515
 * \param desc output location for the descriptor data
516
 * \returns 0 on success or a LIBUSB_ERROR code on failure
517
 */
518
int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev,
519
  struct libusb_device_descriptor *desc)
520
0
{
521
0
  usbi_dbg(DEVICE_CTX(dev), " ");
522
0
  static_assert(sizeof(dev->device_descriptor) == LIBUSB_DT_DEVICE_SIZE,
523
0
          "struct libusb_device_descriptor is not expected size");
524
0
  *desc = dev->device_descriptor;
525
0
  return 0;
526
0
}
527
528
/** \ingroup libusb_desc
529
 * Get the USB configuration descriptor for the currently active configuration.
530
 * This is a non-blocking function which does not involve any requests being
531
 * sent to the device.
532
 *
533
 * \param dev a device
534
 * \param config output location for the USB configuration descriptor. Only
535
 * valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
536
 * after use.
537
 * \returns 0 on success
538
 * \returns \ref LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state
539
 * \returns another LIBUSB_ERROR code on error
540
 * \see libusb_get_config_descriptor
541
 */
542
int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
543
  struct libusb_config_descriptor **config)
544
0
{
545
0
  union usbi_config_desc_buf _config;
546
0
  uint16_t config_len;
547
0
  uint8_t *buf;
548
0
  int r;
549
550
0
  r = get_active_config_descriptor(dev, _config.buf, sizeof(_config.buf));
551
0
  if (r < 0)
552
0
    return r;
553
554
0
  config_len = libusb_le16_to_cpu(_config.desc.wTotalLength);
555
0
  buf = malloc(config_len);
556
0
  if (!buf)
557
0
    return LIBUSB_ERROR_NO_MEM;
558
559
0
  r = get_active_config_descriptor(dev, buf, config_len);
560
0
  if (r >= 0)
561
0
    r = raw_desc_to_config(DEVICE_CTX(dev), buf, r, config);
562
563
0
  free(buf);
564
0
  return r;
565
0
}
566
567
/** \ingroup libusb_desc
568
 * Get a USB configuration descriptor based on its index.
569
 * This is a non-blocking function which does not involve any requests being
570
 * sent to the device.
571
 *
572
 * \param dev a device
573
 * \param config_index the index of the configuration you wish to retrieve
574
 * \param config output location for the USB configuration descriptor. Only
575
 * valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
576
 * after use.
577
 * \returns 0 on success
578
 * \returns \ref LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
579
 * \returns another LIBUSB_ERROR code on error
580
 * \see libusb_get_active_config_descriptor()
581
 * \see libusb_get_config_descriptor_by_value()
582
 */
583
int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
584
  uint8_t config_index, struct libusb_config_descriptor **config)
585
0
{
586
0
  union usbi_config_desc_buf _config;
587
0
  uint16_t config_len;
588
0
  uint8_t *buf;
589
0
  int r;
590
591
0
  usbi_dbg(DEVICE_CTX(dev), "index %u", config_index);
592
0
  if (config_index >= dev->device_descriptor.bNumConfigurations)
593
0
    return LIBUSB_ERROR_NOT_FOUND;
594
595
0
  r = get_config_descriptor(dev, config_index, _config.buf, sizeof(_config.buf));
596
0
  if (r < 0)
597
0
    return r;
598
599
0
  config_len = libusb_le16_to_cpu(_config.desc.wTotalLength);
600
0
  buf = malloc(config_len);
601
0
  if (!buf)
602
0
    return LIBUSB_ERROR_NO_MEM;
603
604
0
  r = get_config_descriptor(dev, config_index, buf, config_len);
605
0
  if (r >= 0)
606
0
    r = raw_desc_to_config(DEVICE_CTX(dev), buf, r, config);
607
608
0
  free(buf);
609
0
  return r;
610
0
}
611
612
/** \ingroup libusb_desc
613
 * Get a USB configuration descriptor with a specific bConfigurationValue.
614
 * This is a non-blocking function which does not involve any requests being
615
 * sent to the device.
616
 *
617
 * \param dev a device
618
 * \param bConfigurationValue the bConfigurationValue of the configuration you
619
 * wish to retrieve
620
 * \param config output location for the USB configuration descriptor. Only
621
 * valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
622
 * after use.
623
 * \returns 0 on success
624
 * \returns \ref LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
625
 * \returns another LIBUSB_ERROR code on error
626
 * \see libusb_get_active_config_descriptor()
627
 * \see libusb_get_config_descriptor()
628
 */
629
int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev,
630
  uint8_t bConfigurationValue, struct libusb_config_descriptor **config)
631
0
{
632
0
  uint8_t idx;
633
0
  int r;
634
635
0
  if (usbi_backend.get_config_descriptor_by_value) {
636
0
    void *buf;
637
638
0
    r = usbi_backend.get_config_descriptor_by_value(dev,
639
0
      bConfigurationValue, &buf);
640
0
    if (r < 0)
641
0
      return r;
642
643
0
    return raw_desc_to_config(DEVICE_CTX(dev), buf, r, config);
644
0
  }
645
646
0
  usbi_dbg(DEVICE_CTX(dev), "value %u", bConfigurationValue);
647
0
  for (idx = 0; idx < dev->device_descriptor.bNumConfigurations; idx++) {
648
0
    union usbi_config_desc_buf _config;
649
650
0
    r = get_config_descriptor(dev, idx, _config.buf, sizeof(_config.buf));
651
0
    if (r < 0)
652
0
      return r;
653
654
0
    if (_config.desc.bConfigurationValue == bConfigurationValue)
655
0
      return libusb_get_config_descriptor(dev, idx, config);
656
0
  }
657
658
0
  return LIBUSB_ERROR_NOT_FOUND;
659
0
}
660
661
/** \ingroup libusb_desc
662
 * Free a configuration descriptor obtained from
663
 * libusb_get_active_config_descriptor() or libusb_get_config_descriptor().
664
 * It is safe to call this function with a NULL config parameter, in which
665
 * case the function simply returns.
666
 *
667
 * \param config the configuration descriptor to free
668
 */
669
void API_EXPORTED libusb_free_config_descriptor(
670
  struct libusb_config_descriptor *config)
671
0
{
672
0
  if (!config)
673
0
    return;
674
675
0
  clear_configuration(config);
676
0
  free(config);
677
0
}
678
679
/** \ingroup libusb_desc
680
 * Get an endpoints superspeed endpoint companion descriptor (if any)
681
 *
682
 * \param ctx the context to operate on, or NULL for the default context
683
 * \param endpoint endpoint descriptor from which to get the superspeed
684
 * endpoint companion descriptor
685
 * \param ep_comp output location for the superspeed endpoint companion
686
 * descriptor. Only valid if 0 was returned. Must be freed with
687
 * libusb_free_ss_endpoint_companion_descriptor() after use.
688
 * \returns 0 on success
689
 * \returns \ref LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
690
 * \returns another LIBUSB_ERROR code on error
691
 */
692
int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor(
693
  libusb_context *ctx,
694
  const struct libusb_endpoint_descriptor *endpoint,
695
  struct libusb_ss_endpoint_companion_descriptor **ep_comp)
696
0
{
697
0
  const struct usbi_descriptor_header *header;
698
0
  const uint8_t *buffer = endpoint->extra;
699
0
  int size = endpoint->extra_length;
700
701
0
  *ep_comp = NULL;
702
703
0
  while (size >= DESC_HEADER_LENGTH) {
704
0
    header = (const struct usbi_descriptor_header *)buffer;
705
0
    if (header->bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMPANION) {
706
0
      if (header->bLength < DESC_HEADER_LENGTH) {
707
0
        usbi_err(ctx, "invalid descriptor length %u",
708
0
           header->bLength);
709
0
        return LIBUSB_ERROR_IO;
710
0
      }
711
0
      buffer += header->bLength;
712
0
      size -= header->bLength;
713
0
      continue;
714
0
    } else if (header->bLength < LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE) {
715
0
      usbi_err(ctx, "invalid ss-ep-comp-desc length %u",
716
0
         header->bLength);
717
0
      return LIBUSB_ERROR_IO;
718
0
    } else if (header->bLength > size) {
719
0
      usbi_err(ctx, "short ss-ep-comp-desc read %d/%u",
720
0
         size, header->bLength);
721
0
      return LIBUSB_ERROR_IO;
722
0
    }
723
724
0
    *ep_comp = malloc(sizeof(**ep_comp));
725
0
    if (!*ep_comp)
726
0
      return LIBUSB_ERROR_NO_MEM;
727
0
    (*ep_comp)->bLength = buffer[0];
728
0
    (*ep_comp)->bDescriptorType = buffer[1];
729
0
    (*ep_comp)->bMaxBurst = buffer[2];
730
0
    (*ep_comp)->bmAttributes = buffer[3];
731
0
    (*ep_comp)->wBytesPerInterval = ReadLittleEndian16(&buffer[4]);
732
0
    return LIBUSB_SUCCESS;
733
0
  }
734
0
  return LIBUSB_ERROR_NOT_FOUND;
735
0
}
736
737
/** \ingroup libusb_desc
738
 * Free a superspeed endpoint companion descriptor obtained from
739
 * libusb_get_ss_endpoint_companion_descriptor().
740
 * It is safe to call this function with a NULL ep_comp parameter, in which
741
 * case the function simply returns.
742
 *
743
 * \param ep_comp the superspeed endpoint companion descriptor to free
744
 */
745
void API_EXPORTED libusb_free_ss_endpoint_companion_descriptor(
746
  struct libusb_ss_endpoint_companion_descriptor *ep_comp)
747
0
{
748
0
  free(ep_comp);
749
0
}
750
751
static int parse_bos(struct libusb_context *ctx,
752
  struct libusb_bos_descriptor **bos,
753
  const uint8_t *buffer, int size)
754
0
{
755
0
  struct libusb_bos_descriptor *_bos;
756
0
  const struct usbi_bos_descriptor *bos_desc;
757
0
  const struct usbi_descriptor_header *header;
758
0
  uint8_t i;
759
760
0
  if (size < LIBUSB_DT_BOS_SIZE) {
761
0
    usbi_err(ctx, "short bos descriptor read %d/%d",
762
0
       size, LIBUSB_DT_BOS_SIZE);
763
0
    return LIBUSB_ERROR_IO;
764
0
  }
765
766
0
  bos_desc = (const struct usbi_bos_descriptor *)buffer;
767
0
  if (bos_desc->bDescriptorType != LIBUSB_DT_BOS) {
768
0
    usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
769
0
       bos_desc->bDescriptorType, LIBUSB_DT_BOS);
770
0
    return LIBUSB_ERROR_IO;
771
0
  } else if (bos_desc->bLength < LIBUSB_DT_BOS_SIZE) {
772
0
    usbi_err(ctx, "invalid bos bLength (%u)", bos_desc->bLength);
773
0
    return LIBUSB_ERROR_IO;
774
0
  } else if (bos_desc->bLength > size) {
775
0
    usbi_err(ctx, "short bos descriptor read %d/%u",
776
0
       size, bos_desc->bLength);
777
0
    return LIBUSB_ERROR_IO;
778
0
  }
779
780
0
  _bos = calloc(1, sizeof(*_bos) + bos_desc->bNumDeviceCaps * sizeof(void *));
781
0
  if (!_bos)
782
0
    return LIBUSB_ERROR_NO_MEM;
783
784
0
  _bos->bLength = buffer[0];
785
0
  _bos->bDescriptorType = buffer[1];
786
0
  _bos->wTotalLength = ReadLittleEndian16(&buffer[2]);
787
0
  _bos->bNumDeviceCaps = buffer[4];
788
0
  buffer += _bos->bLength;
789
0
  size -= _bos->bLength;
790
791
  /* Get the device capability descriptors */
792
0
  for (i = 0; i < _bos->bNumDeviceCaps; i++) {
793
0
    if (size < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) {
794
0
      usbi_warn(ctx, "short dev-cap descriptor read %d/%d",
795
0
          size, LIBUSB_DT_DEVICE_CAPABILITY_SIZE);
796
0
      break;
797
0
    }
798
0
    header = (const struct usbi_descriptor_header *)buffer;
799
0
    if (header->bDescriptorType != LIBUSB_DT_DEVICE_CAPABILITY) {
800
0
      usbi_warn(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
801
0
          header->bDescriptorType, LIBUSB_DT_DEVICE_CAPABILITY);
802
0
      break;
803
0
    } else if (header->bLength < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) {
804
0
      usbi_err(ctx, "invalid dev-cap bLength (%u)",
805
0
         header->bLength);
806
0
      libusb_free_bos_descriptor(_bos);
807
0
      return LIBUSB_ERROR_IO;
808
0
    } else if (header->bLength > size) {
809
0
      usbi_warn(ctx, "short dev-cap descriptor read %d/%u",
810
0
          size, header->bLength);
811
0
      break;
812
0
    }
813
814
0
    _bos->dev_capability[i] = malloc(header->bLength);
815
0
    if (!_bos->dev_capability[i]) {
816
0
      libusb_free_bos_descriptor(_bos);
817
0
      return LIBUSB_ERROR_NO_MEM;
818
0
    }
819
0
    memcpy(_bos->dev_capability[i], buffer, header->bLength);
820
0
    buffer += header->bLength;
821
0
    size -= header->bLength;
822
0
  }
823
0
  _bos->bNumDeviceCaps = i;
824
0
  *bos = _bos;
825
826
0
  return LIBUSB_SUCCESS;
827
0
}
828
829
/** \ingroup libusb_desc
830
 * Get a Binary Object Store (BOS) descriptor
831
 * This is a BLOCKING function, which will send requests to the device.
832
 *
833
 * \param dev_handle the handle of an open libusb device
834
 * \param bos output location for the BOS descriptor. Only valid if 0 was returned.
835
 * Must be freed with \ref libusb_free_bos_descriptor() after use.
836
 * \returns 0 on success
837
 * \returns \ref LIBUSB_ERROR_NOT_FOUND if the device doesn't have a BOS descriptor
838
 * \returns another LIBUSB_ERROR code on error
839
 */
840
int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *dev_handle,
841
  struct libusb_bos_descriptor **bos)
842
0
{
843
0
  union usbi_bos_desc_buf _bos;
844
0
  uint16_t bos_len;
845
0
  uint8_t *bos_data;
846
0
  int r;
847
0
  struct libusb_context *ctx = HANDLE_CTX(dev_handle);
848
849
  /* Read the BOS. This generates 2 requests on the bus,
850
   * one for the header, and one for the full BOS */
851
0
  r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, _bos.buf, sizeof(_bos.buf));
852
0
  if (r < 0) {
853
0
    if (r != LIBUSB_ERROR_PIPE)
854
0
      usbi_err(ctx, "failed to read BOS (%d)", r);
855
0
    return r;
856
0
  }
857
0
  if (r < LIBUSB_DT_BOS_SIZE) {
858
0
    usbi_err(ctx, "short BOS read %d/%d",
859
0
       r, LIBUSB_DT_BOS_SIZE);
860
0
    return LIBUSB_ERROR_IO;
861
0
  }
862
863
0
  bos_len = libusb_le16_to_cpu(_bos.desc.wTotalLength);
864
0
  usbi_dbg(ctx, "found BOS descriptor: size %u bytes, %u capabilities",
865
0
     bos_len, _bos.desc.bNumDeviceCaps);
866
0
  bos_data = calloc(1, bos_len);
867
0
  if (!bos_data)
868
0
    return LIBUSB_ERROR_NO_MEM;
869
870
0
  r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_data, bos_len);
871
0
  if (r >= 0) {
872
0
    if (r != (int)bos_len)
873
0
      usbi_warn(ctx, "short BOS read %d/%u", r, bos_len);
874
0
    r = parse_bos(HANDLE_CTX(dev_handle), bos, bos_data, r);
875
0
  } else {
876
0
    usbi_err(ctx, "failed to read BOS (%d)", r);
877
0
  }
878
879
0
  free(bos_data);
880
0
  return r;
881
0
}
882
883
/** \ingroup libusb_desc
884
 * Free a BOS descriptor obtained from libusb_get_bos_descriptor().
885
 * It is safe to call this function with a NULL bos parameter, in which
886
 * case the function simply returns.
887
 *
888
 * \param bos the BOS descriptor to free
889
 */
890
void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos)
891
0
{
892
0
  uint8_t i;
893
894
0
  if (!bos)
895
0
    return;
896
897
0
  for (i = 0; i < bos->bNumDeviceCaps; i++)
898
0
    free(bos->dev_capability[i]);
899
0
  free(bos);
900
0
}
901
902
/** \ingroup libusb_desc
903
 * Get an USB 2.0 Extension descriptor
904
 *
905
 * \param ctx the context to operate on, or NULL for the default context
906
 * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
907
 * \ref libusb_bos_type::LIBUSB_BT_USB_2_0_EXTENSION
908
 * LIBUSB_BT_USB_2_0_EXTENSION
909
 * \param usb_2_0_extension output location for the USB 2.0 Extension
910
 * descriptor. Only valid if 0 was returned. Must be freed with
911
 * libusb_free_usb_2_0_extension_descriptor() after use.
912
 * \returns 0 on success
913
 * \returns a LIBUSB_ERROR code on error
914
 */
915
int API_EXPORTED libusb_get_usb_2_0_extension_descriptor(
916
  libusb_context *ctx,
917
  struct libusb_bos_dev_capability_descriptor *dev_cap,
918
  struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension)
919
0
{
920
0
  struct libusb_usb_2_0_extension_descriptor *_usb_2_0_extension;
921
922
0
  if (dev_cap->bDevCapabilityType != LIBUSB_BT_USB_2_0_EXTENSION) {
923
0
    usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
924
0
       dev_cap->bDevCapabilityType,
925
0
       LIBUSB_BT_USB_2_0_EXTENSION);
926
0
    return LIBUSB_ERROR_INVALID_PARAM;
927
0
  } else if (dev_cap->bLength < LIBUSB_BT_USB_2_0_EXTENSION_SIZE) {
928
0
    usbi_err(ctx, "short dev-cap descriptor read %u/%d",
929
0
       dev_cap->bLength, LIBUSB_BT_USB_2_0_EXTENSION_SIZE);
930
0
    return LIBUSB_ERROR_IO;
931
0
  }
932
933
0
  _usb_2_0_extension = malloc(sizeof(*_usb_2_0_extension));
934
0
  if (!_usb_2_0_extension)
935
0
    return LIBUSB_ERROR_NO_MEM;
936
937
0
  _usb_2_0_extension->bLength = dev_cap->bLength;
938
0
  _usb_2_0_extension->bDescriptorType = dev_cap->bDescriptorType;
939
0
  _usb_2_0_extension->bDevCapabilityType = dev_cap->bDevCapabilityType;
940
0
  _usb_2_0_extension->bmAttributes = ReadLittleEndian32(dev_cap->dev_capability_data);
941
942
0
  *usb_2_0_extension = _usb_2_0_extension;
943
0
  return LIBUSB_SUCCESS;
944
0
}
945
946
/** \ingroup libusb_desc
947
 * Free a USB 2.0 Extension descriptor obtained from
948
 * libusb_get_usb_2_0_extension_descriptor().
949
 * It is safe to call this function with a NULL usb_2_0_extension parameter,
950
 * in which case the function simply returns.
951
 *
952
 * \param usb_2_0_extension the USB 2.0 Extension descriptor to free
953
 */
954
void API_EXPORTED libusb_free_usb_2_0_extension_descriptor(
955
  struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension)
956
0
{
957
0
  free(usb_2_0_extension);
958
0
}
959
960
/** \ingroup libusb_desc
961
 * Get a SuperSpeed USB Device Capability descriptor
962
 *
963
 * \param ctx the context to operate on, or NULL for the default context
964
 * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
965
 * \ref libusb_bos_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
966
 * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
967
 * \param ss_usb_device_cap output location for the SuperSpeed USB Device
968
 * Capability descriptor. Only valid if 0 was returned. Must be freed with
969
 * libusb_free_ss_usb_device_capability_descriptor() after use.
970
 * \returns 0 on success
971
 * \returns a LIBUSB_ERROR code on error
972
 */
973
int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor(
974
  libusb_context *ctx,
975
  struct libusb_bos_dev_capability_descriptor *dev_cap,
976
  struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap)
977
0
{
978
0
  struct libusb_ss_usb_device_capability_descriptor *_ss_usb_device_cap;
979
980
0
  if (dev_cap->bDevCapabilityType != LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) {
981
0
    usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
982
0
       dev_cap->bDevCapabilityType,
983
0
       LIBUSB_BT_SS_USB_DEVICE_CAPABILITY);
984
0
    return LIBUSB_ERROR_INVALID_PARAM;
985
0
  } else if (dev_cap->bLength < LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) {
986
0
    usbi_err(ctx, "short dev-cap descriptor read %u/%d",
987
0
       dev_cap->bLength, LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE);
988
0
    return LIBUSB_ERROR_IO;
989
0
  }
990
991
0
  _ss_usb_device_cap = malloc(sizeof(*_ss_usb_device_cap));
992
0
  if (!_ss_usb_device_cap)
993
0
    return LIBUSB_ERROR_NO_MEM;
994
995
0
  _ss_usb_device_cap->bLength = dev_cap->bLength;
996
0
  _ss_usb_device_cap->bDescriptorType = dev_cap->bDescriptorType;
997
0
  _ss_usb_device_cap->bDevCapabilityType = dev_cap->bDevCapabilityType;
998
0
  _ss_usb_device_cap->bmAttributes = dev_cap->dev_capability_data[0];
999
0
  _ss_usb_device_cap->wSpeedSupported = ReadLittleEndian16(&dev_cap->dev_capability_data[1]);
1000
0
  _ss_usb_device_cap->bFunctionalitySupport = dev_cap->dev_capability_data[3];
1001
0
  _ss_usb_device_cap->bU1DevExitLat = dev_cap->dev_capability_data[4];
1002
0
  _ss_usb_device_cap->bU2DevExitLat = ReadLittleEndian16(&dev_cap->dev_capability_data[5]);
1003
1004
0
  *ss_usb_device_cap = _ss_usb_device_cap;
1005
0
  return LIBUSB_SUCCESS;
1006
0
}
1007
1008
/// @cond DEV
1009
/** \internal \ingroup libusb_desc
1010
 * We use this private struct only to parse a SuperSpeedPlus device capability
1011
 * descriptor according to section 9.6.2.5 of the USB 3.1 specification.
1012
 * We don't expose it.
1013
 */
1014
struct internal_ssplus_capability_descriptor {
1015
  /** The length of the descriptor. Must be equal to LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE */
1016
  uint8_t  bLength;
1017
1018
  /** The type of the descriptor */
1019
  uint8_t  bDescriptorType;
1020
1021
  /** Must be equal to LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY */
1022
  uint8_t  bDevCapabilityType;
1023
1024
  /** Unused */
1025
  uint8_t  bReserved;
1026
1027
  /** Contains the number of SublinkSpeedIDs */
1028
  uint32_t bmAttributes;
1029
1030
  /** Contains the ssid, minRxLaneCount, and minTxLaneCount */
1031
  uint16_t wFunctionalitySupport;
1032
1033
  /** Unused */
1034
  uint16_t wReserved;
1035
};
1036
/// @endcond
1037
1038
int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor(
1039
  libusb_context *ctx,
1040
  struct libusb_bos_dev_capability_descriptor *dev_cap,
1041
  struct libusb_ssplus_usb_device_capability_descriptor **ssplus_usb_device_cap)
1042
0
{
1043
0
  struct libusb_ssplus_usb_device_capability_descriptor *_ssplus_cap;
1044
1045
  /* Use a private struct to reuse our descriptor parsing system. */
1046
0
  struct internal_ssplus_capability_descriptor parsedDescriptor;
1047
1048
  /* Some size/type checks to make sure everything is in order */
1049
0
  if (dev_cap->bDevCapabilityType != LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY) {
1050
0
    usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
1051
0
       dev_cap->bDevCapabilityType,
1052
0
         LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY);
1053
0
    return LIBUSB_ERROR_INVALID_PARAM;
1054
0
  } else if (dev_cap->bLength < LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE) {
1055
0
    usbi_err(ctx, "short dev-cap descriptor read %u/%d",
1056
0
       dev_cap->bLength, LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE);
1057
0
    return LIBUSB_ERROR_IO;
1058
0
  }
1059
1060
0
  const uint8_t* dev_capability_data = dev_cap->dev_capability_data;
1061
0
  parsedDescriptor.bLength = dev_cap->bLength;
1062
0
  parsedDescriptor.bDescriptorType = dev_cap->bDescriptorType;
1063
0
  parsedDescriptor.bDevCapabilityType = dev_cap->bDevCapabilityType;
1064
0
  parsedDescriptor.bReserved = dev_capability_data[0];
1065
0
  parsedDescriptor.bmAttributes = ReadLittleEndian32(&dev_capability_data[1]);
1066
0
  parsedDescriptor.wFunctionalitySupport = ReadLittleEndian16(&dev_capability_data[5]);
1067
0
  parsedDescriptor.wReserved = ReadLittleEndian16(&dev_capability_data[7]);
1068
1069
0
  uint8_t numSublikSpeedAttributes = (parsedDescriptor.bmAttributes & 0xF) + 1;
1070
0
  _ssplus_cap = malloc(sizeof(struct libusb_ssplus_usb_device_capability_descriptor) + numSublikSpeedAttributes * sizeof(struct libusb_ssplus_sublink_attribute));
1071
0
  if (!_ssplus_cap)
1072
0
    return LIBUSB_ERROR_NO_MEM;
1073
1074
  /* Parse bmAttributes */
1075
0
  _ssplus_cap->numSublinkSpeedAttributes = numSublikSpeedAttributes;
1076
0
  _ssplus_cap->numSublinkSpeedIDs = ((parsedDescriptor.bmAttributes & 0xF0) >> 4) + 1;
1077
1078
  /* Parse wFunctionalitySupport */
1079
0
  _ssplus_cap->ssid = parsedDescriptor.wFunctionalitySupport & 0xF;
1080
0
  _ssplus_cap->minRxLaneCount = (parsedDescriptor.wFunctionalitySupport & 0x0F00) >> 8;
1081
0
  _ssplus_cap->minTxLaneCount = (parsedDescriptor.wFunctionalitySupport & 0xF000) >> 12;
1082
1083
  /* Check that we have enough to read all the sublink attributes */
1084
0
  if (dev_cap->bLength < LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE + _ssplus_cap->numSublinkSpeedAttributes * sizeof(uint32_t)) {
1085
0
    usbi_err(ctx, "short ssplus capability descriptor, unable to read sublinks: Not enough data");
1086
0
    return LIBUSB_ERROR_IO;
1087
0
  }
1088
1089
  /* Read the attributes */
1090
0
  uint8_t* base = ((uint8_t*)dev_cap) + LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE;
1091
0
  for(uint8_t i = 0 ; i < _ssplus_cap->numSublinkSpeedAttributes ; i++) {
1092
0
    uint32_t attr = ReadLittleEndian32(base + i * sizeof(uint32_t));
1093
0
    _ssplus_cap->sublinkSpeedAttributes[i].ssid = attr & 0x0f;
1094
0
    _ssplus_cap->sublinkSpeedAttributes[i].mantissa = attr >> 16;
1095
0
    _ssplus_cap->sublinkSpeedAttributes[i].exponent = (attr >> 4) & 0x3 ;
1096
0
    _ssplus_cap->sublinkSpeedAttributes[i].type = attr & 0x40 ?  LIBUSB_SSPLUS_ATTR_TYPE_ASYM : LIBUSB_SSPLUS_ATTR_TYPE_SYM;
1097
0
    _ssplus_cap->sublinkSpeedAttributes[i].direction = attr & 0x80 ?  LIBUSB_SSPLUS_ATTR_DIR_TX :  LIBUSB_SSPLUS_ATTR_DIR_RX;
1098
0
    _ssplus_cap->sublinkSpeedAttributes[i].protocol = attr & 0x4000 ? LIBUSB_SSPLUS_ATTR_PROT_SSPLUS: LIBUSB_SSPLUS_ATTR_PROT_SS;
1099
0
  }
1100
1101
0
  *ssplus_usb_device_cap = _ssplus_cap;
1102
0
  return LIBUSB_SUCCESS;
1103
0
}
1104
1105
void API_EXPORTED libusb_free_ssplus_usb_device_capability_descriptor(
1106
  struct libusb_ssplus_usb_device_capability_descriptor *ssplus_usb_device_cap)
1107
0
{
1108
0
  free(ssplus_usb_device_cap);
1109
0
}
1110
1111
1112
1113
/** \ingroup libusb_desc
1114
 * Free a SuperSpeed USB Device Capability descriptor obtained from
1115
 * libusb_get_ss_usb_device_capability_descriptor().
1116
 * It is safe to call this function with a NULL ss_usb_device_cap
1117
 * parameter, in which case the function simply returns.
1118
 *
1119
 * \param ss_usb_device_cap the SuperSpeed USB Device Capability descriptor
1120
 * to free
1121
 */
1122
void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor(
1123
  struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap)
1124
0
{
1125
0
  free(ss_usb_device_cap);
1126
0
}
1127
1128
/** \ingroup libusb_desc
1129
 * Get a Container ID descriptor
1130
 *
1131
 * \param ctx the context to operate on, or NULL for the default context
1132
 * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
1133
 * \ref libusb_bos_type::LIBUSB_BT_CONTAINER_ID
1134
 * LIBUSB_BT_CONTAINER_ID
1135
 * \param container_id output location for the Container ID descriptor.
1136
 * Only valid if 0 was returned. Must be freed with
1137
 * libusb_free_container_id_descriptor() after use.
1138
 * \returns 0 on success
1139
 * \returns a LIBUSB_ERROR code on error
1140
 */
1141
int API_EXPORTED libusb_get_container_id_descriptor(libusb_context *ctx,
1142
  struct libusb_bos_dev_capability_descriptor *dev_cap,
1143
  struct libusb_container_id_descriptor **container_id)
1144
0
{
1145
0
  struct libusb_container_id_descriptor *_container_id;
1146
1147
0
  if (dev_cap->bDevCapabilityType != LIBUSB_BT_CONTAINER_ID) {
1148
0
    usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
1149
0
       dev_cap->bDevCapabilityType,
1150
0
       LIBUSB_BT_CONTAINER_ID);
1151
0
    return LIBUSB_ERROR_INVALID_PARAM;
1152
0
  } else if (dev_cap->bLength < LIBUSB_BT_CONTAINER_ID_SIZE) {
1153
0
    usbi_err(ctx, "short dev-cap descriptor read %u/%d",
1154
0
       dev_cap->bLength, LIBUSB_BT_CONTAINER_ID_SIZE);
1155
0
    return LIBUSB_ERROR_IO;
1156
0
  }
1157
1158
0
  _container_id = malloc(sizeof(*_container_id));
1159
0
  if (!_container_id)
1160
0
    return LIBUSB_ERROR_NO_MEM;
1161
1162
0
  _container_id->bLength = dev_cap->bLength;
1163
0
  _container_id->bDescriptorType = dev_cap->bDescriptorType;
1164
0
  _container_id->bDevCapabilityType = dev_cap->bDevCapabilityType;
1165
0
  _container_id->bReserved = dev_cap->dev_capability_data[0];
1166
0
  memcpy(_container_id->ContainerID, &dev_cap->dev_capability_data[1], 16);
1167
1168
0
  *container_id = _container_id;
1169
0
  return LIBUSB_SUCCESS;
1170
0
}
1171
1172
/** \ingroup libusb_desc
1173
 * Free a Container ID descriptor obtained from
1174
 * libusb_get_container_id_descriptor().
1175
 * It is safe to call this function with a NULL container_id parameter,
1176
 * in which case the function simply returns.
1177
 *
1178
 * \param container_id the Container ID descriptor to free
1179
 */
1180
void API_EXPORTED libusb_free_container_id_descriptor(
1181
  struct libusb_container_id_descriptor *container_id)
1182
0
{
1183
0
  free(container_id);
1184
0
}
1185
1186
/** \ingroup libusb_desc
1187
 * Get a platform descriptor
1188
 *
1189
 * Since version 1.0.27, \ref LIBUSB_API_VERSION >= 0x0100010A
1190
 *
1191
 * \param ctx the context to operate on, or NULL for the default context
1192
 * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
1193
 * \ref libusb_bos_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
1194
 * LIBUSB_BT_PLATFORM_DESCRIPTOR
1195
 * \param platform_descriptor output location for the Platform descriptor.
1196
 * Only valid if 0 was returned. Must be freed with
1197
 * libusb_free_platform_descriptor() after use.
1198
 * \returns 0 on success
1199
 * \returns a LIBUSB_ERROR code on error
1200
 */
1201
int API_EXPORTED libusb_get_platform_descriptor(libusb_context *ctx,
1202
  struct libusb_bos_dev_capability_descriptor *dev_cap,
1203
  struct libusb_platform_descriptor **platform_descriptor)
1204
0
{
1205
0
  struct libusb_platform_descriptor *_platform_descriptor;
1206
1207
0
  if (dev_cap->bDevCapabilityType != LIBUSB_BT_PLATFORM_DESCRIPTOR) {
1208
0
    usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
1209
0
       dev_cap->bDevCapabilityType,
1210
0
       LIBUSB_BT_PLATFORM_DESCRIPTOR);
1211
0
    return LIBUSB_ERROR_INVALID_PARAM;
1212
0
  } else if (dev_cap->bLength < LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE) {
1213
0
    usbi_err(ctx, "short dev-cap descriptor read %u/%d",
1214
0
       dev_cap->bLength, LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE);
1215
0
    return LIBUSB_ERROR_IO;
1216
0
  }
1217
1218
0
  _platform_descriptor = malloc(dev_cap->bLength);
1219
0
  if (!_platform_descriptor)
1220
0
    return LIBUSB_ERROR_NO_MEM;
1221
1222
0
  _platform_descriptor->bLength = dev_cap->bLength;
1223
0
  _platform_descriptor->bDescriptorType = dev_cap->bDescriptorType;
1224
0
  _platform_descriptor->bDevCapabilityType = dev_cap->bDevCapabilityType;
1225
0
  _platform_descriptor->bReserved = dev_cap->dev_capability_data[0];
1226
0
  memcpy(_platform_descriptor->PlatformCapabilityUUID, &(dev_cap->dev_capability_data[1]), 16);
1227
1228
  /* Capability data is located after reserved byte and 16 byte UUID */
1229
0
  uint8_t* capability_data = dev_cap->dev_capability_data + 1 + 16;
1230
1231
  /* Capability data length is total descriptor length minus initial fields */
1232
0
  size_t capability_data_length = dev_cap->bLength - (3 + 1 + 16);
1233
1234
0
  memcpy(_platform_descriptor->CapabilityData, capability_data, capability_data_length);
1235
1236
0
  *platform_descriptor = _platform_descriptor;
1237
0
  return LIBUSB_SUCCESS;
1238
0
}
1239
1240
/** \ingroup libusb_desc
1241
 * Free a platform descriptor obtained from
1242
 * libusb_get_platform_descriptor().
1243
 * It is safe to call this function with a NULL platform_descriptor parameter,
1244
 * in which case the function simply returns.
1245
 *
1246
 * \param platform_descriptor the Platform descriptor to free
1247
 */
1248
void API_EXPORTED libusb_free_platform_descriptor(
1249
  struct libusb_platform_descriptor *platform_descriptor)
1250
0
{
1251
0
  free(platform_descriptor);
1252
0
}
1253
1254
/** \ingroup libusb_desc
1255
 * Retrieve a string descriptor in C style ASCII.
1256
 *
1257
 * Wrapper around libusb_get_string_descriptor(). Uses the first language
1258
 * supported by the device.
1259
 *
1260
 * \param dev_handle a device handle
1261
 * \param desc_index the index of the descriptor to retrieve
1262
 * \param data output buffer for ASCII string descriptor
1263
 * \param length size of data buffer
1264
 * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
1265
 */
1266
int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle,
1267
  uint8_t desc_index, unsigned char *data, int length)
1268
0
{
1269
0
  union usbi_string_desc_buf str;
1270
0
  int r;
1271
0
  uint16_t langid, wdata;
1272
1273
  /* Asking for the zero'th index is special - it returns a string
1274
   * descriptor that contains all the language IDs supported by the
1275
   * device. Typically there aren't many - often only one. Language
1276
   * IDs are 16 bit numbers, and they start at the third byte in the
1277
   * descriptor. There's also no point in trying to read descriptor 0
1278
   * with this function. See USB 2.0 specification section 9.6.7 for
1279
   * more information.
1280
   */
1281
1282
0
  if (desc_index == 0)
1283
0
    return LIBUSB_ERROR_INVALID_PARAM;
1284
1285
0
  r = libusb_get_string_descriptor(dev_handle, 0, 0, str.buf, 4);
1286
0
  if (r < 0)
1287
0
    return r;
1288
0
  else if (r != 4 || str.desc.bLength < 4 || str.desc.bDescriptorType != LIBUSB_DT_STRING)
1289
0
    return LIBUSB_ERROR_IO;
1290
0
  else if (str.desc.bLength & 1)
1291
0
    usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for language ID string descriptor", str.desc.bLength);
1292
1293
0
  langid = libusb_le16_to_cpu(str.desc.wData[0]);
1294
0
  r = libusb_get_string_descriptor(dev_handle, desc_index, langid, str.buf, sizeof(str.buf));
1295
0
  if (r < 0)
1296
0
    return r;
1297
0
  else if (r < DESC_HEADER_LENGTH || str.desc.bLength > r || str.desc.bDescriptorType != LIBUSB_DT_STRING)
1298
0
    return LIBUSB_ERROR_IO;
1299
0
  else if ((str.desc.bLength & 1) || str.desc.bLength != r)
1300
0
    usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for string descriptor (read %d)", str.desc.bLength, r);
1301
1302
  /* Stop one byte before the end to leave room for null termination. */
1303
0
  int dest_max = length - 1;
1304
1305
  /* The descriptor has this number of wide characters */
1306
0
  int src_max = (str.desc.bLength - 1 - 1) / 2;
1307
1308
  /* Neither read nor write more than the smallest buffer */
1309
0
  int idx_max = MIN(dest_max, src_max);
1310
1311
0
  int idx;
1312
0
  for (idx = 0; idx < idx_max; ++idx) {
1313
0
    wdata = libusb_le16_to_cpu(str.desc.wData[idx]);
1314
0
    if (wdata < 0x80)
1315
0
      data[idx] = (unsigned char)wdata;
1316
0
    else
1317
0
      data[idx] = '?'; /* non-ASCII */
1318
0
  }
1319
1320
0
  data[idx] = 0; /* null-terminate string */
1321
0
  return idx;
1322
0
}
1323
1324
static int parse_iad_array(struct libusb_context *ctx,
1325
  struct libusb_interface_association_descriptor_array *iad_array,
1326
  const uint8_t *buffer, int size)
1327
0
{
1328
0
  uint8_t i;
1329
0
  struct usbi_descriptor_header header;
1330
0
  int consumed = 0;
1331
0
  const uint8_t *buf = buffer;
1332
0
  struct libusb_interface_association_descriptor *iad;
1333
1334
0
  if (size < LIBUSB_DT_CONFIG_SIZE) {
1335
0
    usbi_err(ctx, "short config descriptor read %d/%d",
1336
0
       size, LIBUSB_DT_CONFIG_SIZE);
1337
0
    return LIBUSB_ERROR_IO;
1338
0
  }
1339
1340
  /* First pass: Iterate through desc list, count number of IADs */
1341
0
  iad_array->length = 0;
1342
0
  while (consumed < size) {
1343
0
    header.bLength = buf[0];
1344
0
    header.bDescriptorType = buf[1];
1345
0
    if (header.bLength < DESC_HEADER_LENGTH) {
1346
0
      usbi_err(ctx, "invalid descriptor bLength %d",
1347
0
         header.bLength);
1348
0
      return LIBUSB_ERROR_IO;
1349
0
    }
1350
0
    else if (header.bLength > size) {
1351
0
      usbi_warn(ctx, "short config descriptor read %d/%u",
1352
0
            size, header.bLength);
1353
0
      return LIBUSB_ERROR_IO;
1354
0
    }
1355
0
    if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION)
1356
0
      iad_array->length++;
1357
0
    buf += header.bLength;
1358
0
    consumed += header.bLength;
1359
0
  }
1360
1361
0
  iad_array->iad = NULL;
1362
0
  if (iad_array->length > 0) {
1363
0
    iad = calloc((size_t)iad_array->length, sizeof(*iad));
1364
0
    if (!iad)
1365
0
      return LIBUSB_ERROR_NO_MEM;
1366
1367
0
    iad_array->iad = iad;
1368
1369
    /* Second pass: Iterate through desc list, fill IAD structures */
1370
0
    int remaining = size;
1371
0
    i = 0;
1372
0
    do {
1373
0
      header.bLength = buffer[0];
1374
0
      header.bDescriptorType = buffer[1];
1375
0
      if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION && (remaining >= LIBUSB_DT_INTERFACE_ASSOCIATION_SIZE)) {
1376
0
        iad[i].bLength = buffer[0];
1377
0
        iad[i].bDescriptorType = buffer[1];
1378
0
        iad[i].bFirstInterface = buffer[2];
1379
0
        iad[i].bInterfaceCount = buffer[3];
1380
0
        iad[i].bFunctionClass = buffer[4];
1381
0
        iad[i].bFunctionSubClass = buffer[5];
1382
0
        iad[i].bFunctionProtocol = buffer[6];
1383
0
        iad[i].iFunction = buffer[7];
1384
0
        i++;
1385
0
      }
1386
1387
0
      remaining -= header.bLength;
1388
0
      if (remaining < DESC_HEADER_LENGTH) {
1389
0
        break;
1390
0
      }
1391
0
      buffer += header.bLength;
1392
0
    } while (1);
1393
0
  }
1394
1395
0
  return LIBUSB_SUCCESS;
1396
0
}
1397
1398
static int raw_desc_to_iad_array(struct libusb_context *ctx, const uint8_t *buf,
1399
    int size, struct libusb_interface_association_descriptor_array **iad_array)
1400
0
{
1401
0
  struct libusb_interface_association_descriptor_array *_iad_array
1402
0
    = calloc(1, sizeof(*_iad_array));
1403
0
  int r;
1404
1405
0
  if (!_iad_array)
1406
0
    return LIBUSB_ERROR_NO_MEM;
1407
1408
0
  r = parse_iad_array(ctx, _iad_array, buf, size);
1409
0
  if (r < 0) {
1410
0
    usbi_err(ctx, "parse_iad_array failed with error %d", r);
1411
0
    free(_iad_array);
1412
0
    return r;
1413
0
  }
1414
1415
0
  *iad_array = _iad_array;
1416
0
  return LIBUSB_SUCCESS;
1417
0
}
1418
1419
/** \ingroup libusb_desc
1420
 * Get an array of interface association descriptors (IAD) for a given
1421
 * configuration.
1422
 * This is a non-blocking function which does not involve any requests being
1423
 * sent to the device.
1424
 *
1425
 * \param dev a device
1426
 * \param config_index the index of the configuration you wish to retrieve the
1427
 * IADs for.
1428
 * \param iad_array output location for the array of IADs. Only valid if 0 was
1429
 * returned. Must be freed with libusb_free_interface_association_descriptors()
1430
 * after use. It's possible that a given configuration contains no IADs. In this
1431
 * case the iad_array is still output, but will have 'length' field set to 0, and
1432
 * iad field set to NULL.
1433
 * \returns 0 on success
1434
 * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
1435
 * \returns another LIBUSB_ERROR code on error
1436
 * \see libusb_get_active_interface_association_descriptors()
1437
 */
1438
int API_EXPORTED libusb_get_interface_association_descriptors(libusb_device *dev,
1439
  uint8_t config_index, struct libusb_interface_association_descriptor_array **iad_array)
1440
0
{
1441
0
  union usbi_config_desc_buf _config;
1442
0
  uint16_t config_len;
1443
0
  uint8_t *buf;
1444
0
  int r;
1445
1446
0
  if (!iad_array)
1447
0
    return LIBUSB_ERROR_INVALID_PARAM;
1448
1449
0
  usbi_dbg(DEVICE_CTX(dev), "IADs for config index %u", config_index);
1450
0
  if (config_index >= dev->device_descriptor.bNumConfigurations)
1451
0
    return LIBUSB_ERROR_NOT_FOUND;
1452
1453
0
  r = get_config_descriptor(dev, config_index, _config.buf, sizeof(_config.buf));
1454
0
  if (r < 0)
1455
0
    return r;
1456
1457
0
  config_len = libusb_le16_to_cpu(_config.desc.wTotalLength);
1458
0
  buf = malloc(config_len);
1459
0
  if (!buf)
1460
0
    return LIBUSB_ERROR_NO_MEM;
1461
1462
0
  r = get_config_descriptor(dev, config_index, buf, config_len);
1463
0
  if (r >= 0)
1464
0
    r = raw_desc_to_iad_array(DEVICE_CTX(dev), buf, r, iad_array);
1465
1466
0
  free(buf);
1467
0
  return r;
1468
0
}
1469
1470
/** \ingroup libusb_desc
1471
 * Get an array of interface association descriptors (IAD) for the currently
1472
 * active configuration.
1473
 * This is a non-blocking function which does not involve any requests being
1474
 * sent to the device.
1475
 *
1476
 * \param dev a device
1477
 * \param iad_array output location for the array of IADs. Only valid if 0 was
1478
 * returned. Must be freed with libusb_free_interface_association_descriptors()
1479
 * after use. It's possible that a given configuration contains no IADs. In this
1480
 * case the iad_array is still output, but will have 'length' field set to 0, and
1481
 * iad field set to NULL.
1482
 * \returns 0 on success
1483
 * \returns LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state
1484
 * \returns another LIBUSB_ERROR code on error
1485
 * \see libusb_get_interface_association_descriptors
1486
 */
1487
int API_EXPORTED libusb_get_active_interface_association_descriptors(libusb_device *dev,
1488
  struct libusb_interface_association_descriptor_array **iad_array)
1489
0
{
1490
0
  union usbi_config_desc_buf _config;
1491
0
  uint16_t config_len;
1492
0
  uint8_t *buf;
1493
0
  int r;
1494
1495
0
  if (!iad_array)
1496
0
    return LIBUSB_ERROR_INVALID_PARAM;
1497
1498
0
  r = get_active_config_descriptor(dev, _config.buf, sizeof(_config.buf));
1499
0
  if (r < 0)
1500
0
    return r;
1501
1502
0
  config_len = libusb_le16_to_cpu(_config.desc.wTotalLength);
1503
0
  buf = malloc(config_len);
1504
0
  if (!buf)
1505
0
    return LIBUSB_ERROR_NO_MEM;
1506
1507
0
  r = get_active_config_descriptor(dev, buf, config_len);
1508
0
  if (r >= 0)
1509
0
    r = raw_desc_to_iad_array(DEVICE_CTX(dev), buf, r, iad_array);
1510
0
  free(buf);
1511
0
  return r;
1512
0
}
1513
1514
/** \ingroup libusb_desc
1515
 * Free an array of interface association descriptors (IADs) obtained from
1516
 * libusb_get_interface_association_descriptors() or
1517
 * libusb_get_active_interface_association_descriptors().
1518
 * It is safe to call this function with a NULL iad_array parameter, in which
1519
 * case the function simply returns.
1520
 *
1521
 * \param iad_array the IAD array to free
1522
 */
1523
void API_EXPORTED libusb_free_interface_association_descriptors(
1524
  struct libusb_interface_association_descriptor_array *iad_array)
1525
0
{
1526
0
  if (!iad_array)
1527
0
    return;
1528
1529
0
  if (iad_array->iad)
1530
0
    free((void*)iad_array->iad);
1531
0
  free(iad_array);
1532
0
}