usb 2.17.0 → 3.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -4
- package/README.md +25 -516
- package/dist/index.d.ts +67 -13
- package/dist/index.js +333 -64
- package/index.d.ts +89 -0
- package/index.js +583 -0
- package/package.json +53 -33
- package/CHANGELOG.md +0 -294
- package/binding.gyp +0 -128
- package/dist/index.js.map +0 -1
- package/dist/usb/bindings.d.ts +0 -266
- package/dist/usb/bindings.js +0 -10
- package/dist/usb/bindings.js.map +0 -1
- package/dist/usb/capability.d.ts +0 -13
- package/dist/usb/capability.js +0 -17
- package/dist/usb/capability.js.map +0 -1
- package/dist/usb/descriptors.d.ts +0 -128
- package/dist/usb/descriptors.js +0 -3
- package/dist/usb/descriptors.js.map +0 -1
- package/dist/usb/device.d.ts +0 -100
- package/dist/usb/device.js +0 -297
- package/dist/usb/device.js.map +0 -1
- package/dist/usb/endpoint.d.ts +0 -94
- package/dist/usb/endpoint.js +0 -219
- package/dist/usb/endpoint.js.map +0 -1
- package/dist/usb/index.d.ts +0 -31
- package/dist/usb/index.js +0 -116
- package/dist/usb/index.js.map +0 -1
- package/dist/usb/interface.d.ts +0 -80
- package/dist/usb/interface.js +0 -133
- package/dist/usb/interface.js.map +0 -1
- package/dist/webusb/index.d.ts +0 -64
- package/dist/webusb/index.js +0 -295
- package/dist/webusb/index.js.map +0 -1
- package/dist/webusb/webusb-device.d.ts +0 -54
- package/dist/webusb/webusb-device.js +0 -434
- package/dist/webusb/webusb-device.js.map +0 -1
- package/libusb/.clang-tidy +0 -34
- package/libusb/.codespellrc +0 -3
- package/libusb/.private/README.txt +0 -5
- package/libusb/.private/appveyor_build.sh +0 -26
- package/libusb/.private/bm.sh +0 -54
- package/libusb/.private/ci-build.sh +0 -92
- package/libusb/.private/ci-container-build.sh +0 -67
- package/libusb/.private/post-rewrite.sh +0 -32
- package/libusb/.private/pre-commit.sh +0 -52
- package/libusb/.private/wbs.txt +0 -43
- package/libusb/.travis.yml +0 -58
- package/libusb/AUTHORS +0 -231
- package/libusb/COPYING +0 -504
- package/libusb/ChangeLog +0 -365
- package/libusb/HACKING +0 -25
- package/libusb/INSTALL_WIN.txt +0 -52
- package/libusb/KEYS +0 -123
- package/libusb/Makefile.am +0 -50
- package/libusb/NEWS +0 -2
- package/libusb/PORTING +0 -94
- package/libusb/README +0 -29
- package/libusb/README.git +0 -41
- package/libusb/TODO +0 -2
- package/libusb/Xcode/common.xcconfig +0 -92
- package/libusb/Xcode/config.h +0 -31
- package/libusb/Xcode/debug.xcconfig +0 -32
- package/libusb/Xcode/libusb.xcconfig +0 -21
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +0 -1391
- package/libusb/Xcode/libusb_debug.xcconfig +0 -21
- package/libusb/Xcode/libusb_release.xcconfig +0 -21
- package/libusb/Xcode/release.xcconfig +0 -30
- package/libusb/android/README +0 -152
- package/libusb/android/config.h +0 -55
- package/libusb/android/examples/unrooted_android.c +0 -301
- package/libusb/android/examples/unrooted_android.h +0 -36
- package/libusb/android/jni/Android.mk +0 -23
- package/libusb/android/jni/Application.mk +0 -40
- package/libusb/android/jni/examples.mk +0 -168
- package/libusb/android/jni/libusb.mk +0 -60
- package/libusb/android/jni/tests.mk +0 -45
- package/libusb/appveyor.yml +0 -108
- package/libusb/autogen.sh +0 -10
- package/libusb/bootstrap.sh +0 -10
- package/libusb/configure.ac +0 -450
- package/libusb/doc/Makefile.in +0 -22
- package/libusb/doc/doxygen.cfg.in +0 -2571
- package/libusb/doc/libusb.png +0 -0
- package/libusb/examples/Makefile.am +0 -12
- package/libusb/examples/dpfp.c +0 -711
- package/libusb/examples/ezusb.c +0 -846
- package/libusb/examples/ezusb.h +0 -109
- package/libusb/examples/fxload.c +0 -310
- package/libusb/examples/hotplugtest.c +0 -147
- package/libusb/examples/listdevs.c +0 -73
- package/libusb/examples/sam3u_benchmark.c +0 -228
- package/libusb/examples/testlibusb.c +0 -312
- package/libusb/examples/xusb.c +0 -1254
- package/libusb/libusb/Makefile.am +0 -98
- package/libusb/libusb/Makefile.am.extra +0 -26
- package/libusb/libusb/core.c +0 -2925
- package/libusb/libusb/descriptor.c +0 -1558
- package/libusb/libusb/hotplug.c +0 -489
- package/libusb/libusb/io.c +0 -2865
- package/libusb/libusb/libusb-1.0.def +0 -199
- package/libusb/libusb/libusb-1.0.rc +0 -53
- package/libusb/libusb/libusb.h +0 -2421
- package/libusb/libusb/libusbi.h +0 -1535
- package/libusb/libusb/os/darwin_usb.c +0 -2977
- package/libusb/libusb/os/darwin_usb.h +0 -156
- package/libusb/libusb/os/emscripten_webusb.cpp +0 -875
- package/libusb/libusb/os/events_posix.c +0 -340
- package/libusb/libusb/os/events_posix.h +0 -62
- package/libusb/libusb/os/events_windows.c +0 -214
- package/libusb/libusb/os/events_windows.h +0 -46
- package/libusb/libusb/os/haiku_pollfs.cpp +0 -372
- package/libusb/libusb/os/haiku_usb.h +0 -113
- package/libusb/libusb/os/haiku_usb_backend.cpp +0 -532
- package/libusb/libusb/os/haiku_usb_raw.cpp +0 -231
- package/libusb/libusb/os/haiku_usb_raw.h +0 -188
- package/libusb/libusb/os/linux_netlink.c +0 -401
- package/libusb/libusb/os/linux_udev.c +0 -321
- package/libusb/libusb/os/linux_usbfs.c +0 -2829
- package/libusb/libusb/os/linux_usbfs.h +0 -221
- package/libusb/libusb/os/netbsd_usb.c +0 -617
- package/libusb/libusb/os/null_usb.c +0 -111
- package/libusb/libusb/os/openbsd_usb.c +0 -700
- package/libusb/libusb/os/sunos_usb.c +0 -1619
- package/libusb/libusb/os/sunos_usb.h +0 -79
- package/libusb/libusb/os/threads_posix.c +0 -126
- package/libusb/libusb/os/threads_posix.h +0 -98
- package/libusb/libusb/os/threads_windows.c +0 -40
- package/libusb/libusb/os/threads_windows.h +0 -113
- package/libusb/libusb/os/windows_common.c +0 -923
- package/libusb/libusb/os/windows_common.h +0 -424
- package/libusb/libusb/os/windows_usbdk.c +0 -724
- package/libusb/libusb/os/windows_usbdk.h +0 -106
- package/libusb/libusb/os/windows_winusb.c +0 -4766
- package/libusb/libusb/os/windows_winusb.h +0 -787
- package/libusb/libusb/strerror.c +0 -223
- package/libusb/libusb/sync.c +0 -342
- package/libusb/libusb/version.h +0 -18
- package/libusb/libusb/version_nano.h +0 -1
- package/libusb/libusb-1.0.pc.in +0 -11
- package/libusb/msvc/Base.props +0 -60
- package/libusb/msvc/Configuration.Application.props +0 -7
- package/libusb/msvc/Configuration.Base.props +0 -47
- package/libusb/msvc/Configuration.DynamicLibrary.props +0 -21
- package/libusb/msvc/Configuration.StaticLibrary.props +0 -7
- package/libusb/msvc/ProjectConfigurations.Base.props +0 -69
- package/libusb/msvc/build_all.ps1 +0 -17
- package/libusb/msvc/config.h +0 -58
- package/libusb/msvc/dpfp.vcxproj +0 -33
- package/libusb/msvc/dpfp_threaded.vcxproj +0 -38
- package/libusb/msvc/fxload.vcxproj +0 -46
- package/libusb/msvc/getopt/getopt.c +0 -1060
- package/libusb/msvc/getopt/getopt.h +0 -180
- package/libusb/msvc/getopt/getopt1.c +0 -188
- package/libusb/msvc/getopt.vcxproj +0 -33
- package/libusb/msvc/hotplugtest.vcxproj +0 -32
- package/libusb/msvc/init_context.vcxproj +0 -35
- package/libusb/msvc/libusb.sln +0 -542
- package/libusb/msvc/libusb_dll.vcxproj +0 -61
- package/libusb/msvc/libusb_static.vcxproj +0 -49
- package/libusb/msvc/listdevs.vcxproj +0 -32
- package/libusb/msvc/sam3u_benchmark.vcxproj +0 -33
- package/libusb/msvc/set_option.vcxproj +0 -35
- package/libusb/msvc/stress.vcxproj +0 -35
- package/libusb/msvc/stress_mt.vcxproj +0 -33
- package/libusb/msvc/testlibusb.vcxproj +0 -32
- package/libusb/msvc/xusb.vcxproj +0 -38
- package/libusb/tests/Makefile.am +0 -40
- package/libusb/tests/init_context.c +0 -153
- package/libusb/tests/libusb_testlib.h +0 -76
- package/libusb/tests/macos.c +0 -130
- package/libusb/tests/set_option.c +0 -253
- package/libusb/tests/stress.c +0 -172
- package/libusb/tests/stress_mt.c +0 -267
- package/libusb/tests/testlib.c +0 -184
- package/libusb/tests/umockdev.c +0 -1175
- package/libusb/tests/webusb-test-shim/index.js +0 -12
- package/libusb/tests/webusb-test-shim/package-lock.json +0 -50
- package/libusb/tests/webusb-test-shim/package.json +0 -10
- package/libusb.gypi +0 -154
- package/libusb_config/config.h +0 -1
- package/prebuilds/android-arm/node.napi.armv7.node +0 -0
- package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
- package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/linux-ia32/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-arm64/node.napi.node +0 -0
- package/prebuilds/win32-ia32/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/device.cc +0 -439
- package/src/helpers.h +0 -64
- package/src/hotplug/hotplug.h +0 -22
- package/src/hotplug/libusb.cc +0 -90
- package/src/hotplug/windows.cc +0 -168
- package/src/node_usb.cc +0 -314
- package/src/node_usb.h +0 -131
- package/src/thread_name.cc +0 -79
- package/src/thread_name.h +0 -11
- package/src/transfer.cc +0 -143
- package/src/uv_async_queue.h +0 -41
- package/test/usb.coffee +0 -250
- package/test/webusb.coffee +0 -227
- package/test/worker.cjs +0 -13
|
@@ -1,1558 +0,0 @@
|
|
|
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
|
-
#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
|
-
{
|
|
35
|
-
return (uint16_t)((uint16_t)p[1] << 8 |
|
|
36
|
-
(uint16_t)p[0]);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
static inline uint32_t ReadLittleEndian32(const uint8_t p[4])
|
|
40
|
-
{
|
|
41
|
-
return (uint32_t)((uint32_t)p[3] << 24 |
|
|
42
|
-
(uint32_t)p[2] << 16 |
|
|
43
|
-
(uint32_t)p[1] << 8 |
|
|
44
|
-
(uint32_t)p[0]);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint)
|
|
48
|
-
{
|
|
49
|
-
free((void *)endpoint->extra);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
static int parse_endpoint(struct libusb_context *ctx,
|
|
53
|
-
struct libusb_endpoint_descriptor *endpoint, const uint8_t *buffer, int size)
|
|
54
|
-
{
|
|
55
|
-
const struct usbi_descriptor_header *header;
|
|
56
|
-
const uint8_t *begin;
|
|
57
|
-
void *extra;
|
|
58
|
-
int parsed = 0;
|
|
59
|
-
|
|
60
|
-
if (size < DESC_HEADER_LENGTH) {
|
|
61
|
-
usbi_err(ctx, "short endpoint descriptor read %d/%d",
|
|
62
|
-
size, DESC_HEADER_LENGTH);
|
|
63
|
-
return LIBUSB_ERROR_IO;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
header = (const struct usbi_descriptor_header *)buffer;
|
|
67
|
-
if (header->bDescriptorType != LIBUSB_DT_ENDPOINT) {
|
|
68
|
-
usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
|
|
69
|
-
header->bDescriptorType, LIBUSB_DT_ENDPOINT);
|
|
70
|
-
return parsed;
|
|
71
|
-
} else if (header->bLength < LIBUSB_DT_ENDPOINT_SIZE) {
|
|
72
|
-
usbi_err(ctx, "invalid endpoint bLength (%u)", header->bLength);
|
|
73
|
-
return LIBUSB_ERROR_IO;
|
|
74
|
-
} else if (header->bLength > size) {
|
|
75
|
-
usbi_warn(ctx, "short endpoint descriptor read %d/%u",
|
|
76
|
-
size, header->bLength);
|
|
77
|
-
return parsed;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
endpoint->bLength = buffer[0];
|
|
81
|
-
endpoint->bDescriptorType = buffer[1];
|
|
82
|
-
endpoint->bEndpointAddress = buffer[2];
|
|
83
|
-
endpoint->bmAttributes = buffer[3];
|
|
84
|
-
endpoint->wMaxPacketSize = ReadLittleEndian16(&buffer[4]);
|
|
85
|
-
endpoint->bInterval = buffer[6];
|
|
86
|
-
if (header->bLength >= LIBUSB_DT_ENDPOINT_AUDIO_SIZE) {
|
|
87
|
-
endpoint->bRefresh = buffer[7];
|
|
88
|
-
endpoint->bSynchAddress = buffer[8];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
buffer += header->bLength;
|
|
92
|
-
size -= header->bLength;
|
|
93
|
-
parsed += header->bLength;
|
|
94
|
-
|
|
95
|
-
/* Skip over the rest of the Class Specific or Vendor Specific */
|
|
96
|
-
/* descriptors */
|
|
97
|
-
begin = buffer;
|
|
98
|
-
while (size >= DESC_HEADER_LENGTH) {
|
|
99
|
-
header = (const struct usbi_descriptor_header *)buffer;
|
|
100
|
-
if (header->bLength < DESC_HEADER_LENGTH) {
|
|
101
|
-
usbi_err(ctx, "invalid extra ep desc len (%u)",
|
|
102
|
-
header->bLength);
|
|
103
|
-
return LIBUSB_ERROR_IO;
|
|
104
|
-
} else if (header->bLength > size) {
|
|
105
|
-
usbi_warn(ctx, "short extra ep desc read %d/%u",
|
|
106
|
-
size, header->bLength);
|
|
107
|
-
return parsed;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/* If we find another "proper" descriptor then we're done */
|
|
111
|
-
if (header->bDescriptorType == LIBUSB_DT_ENDPOINT ||
|
|
112
|
-
header->bDescriptorType == LIBUSB_DT_INTERFACE ||
|
|
113
|
-
header->bDescriptorType == LIBUSB_DT_CONFIG ||
|
|
114
|
-
header->bDescriptorType == LIBUSB_DT_DEVICE)
|
|
115
|
-
break;
|
|
116
|
-
|
|
117
|
-
usbi_dbg(ctx, "skipping descriptor 0x%x", header->bDescriptorType);
|
|
118
|
-
buffer += header->bLength;
|
|
119
|
-
size -= header->bLength;
|
|
120
|
-
parsed += header->bLength;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/* Copy any unknown descriptors into a storage area for drivers */
|
|
124
|
-
/* to later parse */
|
|
125
|
-
ptrdiff_t len = buffer - begin;
|
|
126
|
-
if (len <= 0)
|
|
127
|
-
return parsed;
|
|
128
|
-
|
|
129
|
-
extra = malloc((size_t)len);
|
|
130
|
-
if (!extra)
|
|
131
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
132
|
-
|
|
133
|
-
memcpy(extra, begin, (size_t)len);
|
|
134
|
-
endpoint->extra = extra;
|
|
135
|
-
endpoint->extra_length = (int)len;
|
|
136
|
-
|
|
137
|
-
return parsed;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
static void clear_interface(struct libusb_interface *usb_interface)
|
|
141
|
-
{
|
|
142
|
-
int i;
|
|
143
|
-
|
|
144
|
-
if (usb_interface->altsetting) {
|
|
145
|
-
for (i = 0; i < usb_interface->num_altsetting; i++) {
|
|
146
|
-
struct libusb_interface_descriptor *ifp =
|
|
147
|
-
(struct libusb_interface_descriptor *)
|
|
148
|
-
usb_interface->altsetting + i;
|
|
149
|
-
|
|
150
|
-
free((void *)ifp->extra);
|
|
151
|
-
if (ifp->endpoint) {
|
|
152
|
-
uint8_t j;
|
|
153
|
-
|
|
154
|
-
for (j = 0; j < ifp->bNumEndpoints; j++)
|
|
155
|
-
clear_endpoint((struct libusb_endpoint_descriptor *)
|
|
156
|
-
ifp->endpoint + j);
|
|
157
|
-
}
|
|
158
|
-
free((void *)ifp->endpoint);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
free((void *)usb_interface->altsetting);
|
|
162
|
-
usb_interface->altsetting = NULL;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
static int parse_interface(libusb_context *ctx,
|
|
166
|
-
struct libusb_interface *usb_interface, const uint8_t *buffer, int size)
|
|
167
|
-
{
|
|
168
|
-
int r;
|
|
169
|
-
int parsed = 0;
|
|
170
|
-
int interface_number = -1;
|
|
171
|
-
const struct usbi_descriptor_header *header;
|
|
172
|
-
const struct usbi_interface_descriptor *if_desc;
|
|
173
|
-
struct libusb_interface_descriptor *ifp;
|
|
174
|
-
const uint8_t *begin;
|
|
175
|
-
|
|
176
|
-
while (size >= LIBUSB_DT_INTERFACE_SIZE) {
|
|
177
|
-
struct libusb_interface_descriptor *altsetting;
|
|
178
|
-
|
|
179
|
-
altsetting = realloc((void *)usb_interface->altsetting,
|
|
180
|
-
sizeof(*altsetting) * (size_t)(usb_interface->num_altsetting + 1));
|
|
181
|
-
if (!altsetting) {
|
|
182
|
-
r = LIBUSB_ERROR_NO_MEM;
|
|
183
|
-
goto err;
|
|
184
|
-
}
|
|
185
|
-
usb_interface->altsetting = altsetting;
|
|
186
|
-
|
|
187
|
-
ifp = altsetting + usb_interface->num_altsetting;
|
|
188
|
-
ifp->bLength = buffer[0];
|
|
189
|
-
ifp->bDescriptorType = buffer[1];
|
|
190
|
-
ifp->bInterfaceNumber = buffer[2];
|
|
191
|
-
ifp->bAlternateSetting = buffer[3];
|
|
192
|
-
ifp->bNumEndpoints = buffer[4];
|
|
193
|
-
ifp->bInterfaceClass = buffer[5];
|
|
194
|
-
ifp->bInterfaceSubClass = buffer[6];
|
|
195
|
-
ifp->bInterfaceProtocol = buffer[7];
|
|
196
|
-
ifp->iInterface = buffer[8];
|
|
197
|
-
if (ifp->bDescriptorType != LIBUSB_DT_INTERFACE) {
|
|
198
|
-
usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
|
|
199
|
-
ifp->bDescriptorType, LIBUSB_DT_INTERFACE);
|
|
200
|
-
return parsed;
|
|
201
|
-
} else if (ifp->bLength < LIBUSB_DT_INTERFACE_SIZE) {
|
|
202
|
-
usbi_err(ctx, "invalid interface bLength (%u)",
|
|
203
|
-
ifp->bLength);
|
|
204
|
-
r = LIBUSB_ERROR_IO;
|
|
205
|
-
goto err;
|
|
206
|
-
} else if (ifp->bLength > size) {
|
|
207
|
-
usbi_warn(ctx, "short intf descriptor read %d/%u",
|
|
208
|
-
size, ifp->bLength);
|
|
209
|
-
return parsed;
|
|
210
|
-
} else if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
|
|
211
|
-
usbi_err(ctx, "too many endpoints (%u)", ifp->bNumEndpoints);
|
|
212
|
-
r = LIBUSB_ERROR_IO;
|
|
213
|
-
goto err;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
usb_interface->num_altsetting++;
|
|
217
|
-
ifp->extra = NULL;
|
|
218
|
-
ifp->extra_length = 0;
|
|
219
|
-
ifp->endpoint = NULL;
|
|
220
|
-
|
|
221
|
-
if (interface_number == -1)
|
|
222
|
-
interface_number = ifp->bInterfaceNumber;
|
|
223
|
-
|
|
224
|
-
/* Skip over the interface */
|
|
225
|
-
buffer += ifp->bLength;
|
|
226
|
-
parsed += ifp->bLength;
|
|
227
|
-
size -= ifp->bLength;
|
|
228
|
-
|
|
229
|
-
begin = buffer;
|
|
230
|
-
|
|
231
|
-
/* Skip over any interface, class or vendor descriptors */
|
|
232
|
-
while (size >= DESC_HEADER_LENGTH) {
|
|
233
|
-
header = (const struct usbi_descriptor_header *)buffer;
|
|
234
|
-
if (header->bLength < DESC_HEADER_LENGTH) {
|
|
235
|
-
usbi_err(ctx,
|
|
236
|
-
"invalid extra intf desc len (%u)",
|
|
237
|
-
header->bLength);
|
|
238
|
-
r = LIBUSB_ERROR_IO;
|
|
239
|
-
goto err;
|
|
240
|
-
} else if (header->bLength > size) {
|
|
241
|
-
usbi_warn(ctx,
|
|
242
|
-
"short extra intf desc read %d/%u",
|
|
243
|
-
size, header->bLength);
|
|
244
|
-
return parsed;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/* If we find another "proper" descriptor then we're done */
|
|
248
|
-
if (header->bDescriptorType == LIBUSB_DT_INTERFACE ||
|
|
249
|
-
header->bDescriptorType == LIBUSB_DT_ENDPOINT ||
|
|
250
|
-
header->bDescriptorType == LIBUSB_DT_CONFIG ||
|
|
251
|
-
header->bDescriptorType == LIBUSB_DT_DEVICE)
|
|
252
|
-
break;
|
|
253
|
-
|
|
254
|
-
buffer += header->bLength;
|
|
255
|
-
parsed += header->bLength;
|
|
256
|
-
size -= header->bLength;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/* Copy any unknown descriptors into a storage area for */
|
|
260
|
-
/* drivers to later parse */
|
|
261
|
-
ptrdiff_t len = buffer - begin;
|
|
262
|
-
if (len > 0) {
|
|
263
|
-
void *extra = malloc((size_t)len);
|
|
264
|
-
|
|
265
|
-
if (!extra) {
|
|
266
|
-
r = LIBUSB_ERROR_NO_MEM;
|
|
267
|
-
goto err;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
memcpy(extra, begin, (size_t)len);
|
|
271
|
-
ifp->extra = extra;
|
|
272
|
-
ifp->extra_length = (int)len;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
if (ifp->bNumEndpoints > 0) {
|
|
276
|
-
struct libusb_endpoint_descriptor *endpoint;
|
|
277
|
-
uint8_t i;
|
|
278
|
-
|
|
279
|
-
endpoint = calloc(ifp->bNumEndpoints, sizeof(*endpoint));
|
|
280
|
-
if (!endpoint) {
|
|
281
|
-
r = LIBUSB_ERROR_NO_MEM;
|
|
282
|
-
goto err;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
ifp->endpoint = endpoint;
|
|
286
|
-
for (i = 0; i < ifp->bNumEndpoints; i++) {
|
|
287
|
-
r = parse_endpoint(ctx, endpoint + i, buffer, size);
|
|
288
|
-
if (r < 0)
|
|
289
|
-
goto err;
|
|
290
|
-
if (r == 0) {
|
|
291
|
-
ifp->bNumEndpoints = i;
|
|
292
|
-
break;
|
|
293
|
-
}
|
|
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
|
-
if_desc = (const struct usbi_interface_descriptor *)buffer;
|
|
303
|
-
if (size < LIBUSB_DT_INTERFACE_SIZE ||
|
|
304
|
-
if_desc->bDescriptorType != LIBUSB_DT_INTERFACE ||
|
|
305
|
-
if_desc->bInterfaceNumber != interface_number)
|
|
306
|
-
return parsed;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return parsed;
|
|
310
|
-
err:
|
|
311
|
-
clear_interface(usb_interface);
|
|
312
|
-
return r;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
static void clear_configuration(struct libusb_config_descriptor *config)
|
|
316
|
-
{
|
|
317
|
-
uint8_t i;
|
|
318
|
-
|
|
319
|
-
if (config->interface) {
|
|
320
|
-
for (i = 0; i < config->bNumInterfaces; i++)
|
|
321
|
-
clear_interface((struct libusb_interface *)
|
|
322
|
-
config->interface + i);
|
|
323
|
-
}
|
|
324
|
-
free((void *)config->interface);
|
|
325
|
-
free((void *)config->extra);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
static int parse_configuration(struct libusb_context *ctx,
|
|
329
|
-
struct libusb_config_descriptor *config, const uint8_t *buffer, int size)
|
|
330
|
-
{
|
|
331
|
-
uint8_t i;
|
|
332
|
-
int r;
|
|
333
|
-
const struct usbi_descriptor_header *header;
|
|
334
|
-
struct libusb_interface *usb_interface;
|
|
335
|
-
|
|
336
|
-
if (size < LIBUSB_DT_CONFIG_SIZE) {
|
|
337
|
-
usbi_err(ctx, "short config descriptor read %d/%d",
|
|
338
|
-
size, LIBUSB_DT_CONFIG_SIZE);
|
|
339
|
-
return LIBUSB_ERROR_IO;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
config->bLength = buffer[0];
|
|
343
|
-
config->bDescriptorType = buffer[1];
|
|
344
|
-
config->wTotalLength = ReadLittleEndian16(&buffer[2]);
|
|
345
|
-
config->bNumInterfaces = buffer[4];
|
|
346
|
-
config->bConfigurationValue = buffer[5];
|
|
347
|
-
config->iConfiguration = buffer[6];
|
|
348
|
-
config->bmAttributes = buffer[7];
|
|
349
|
-
config->MaxPower = buffer[8];
|
|
350
|
-
if (config->bDescriptorType != LIBUSB_DT_CONFIG) {
|
|
351
|
-
usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
|
|
352
|
-
config->bDescriptorType, LIBUSB_DT_CONFIG);
|
|
353
|
-
return LIBUSB_ERROR_IO;
|
|
354
|
-
} else if (config->bLength < LIBUSB_DT_CONFIG_SIZE) {
|
|
355
|
-
usbi_err(ctx, "invalid config bLength (%u)", config->bLength);
|
|
356
|
-
return LIBUSB_ERROR_IO;
|
|
357
|
-
} else if (config->bLength > size) {
|
|
358
|
-
usbi_err(ctx, "short config descriptor read %d/%u",
|
|
359
|
-
size, config->bLength);
|
|
360
|
-
return LIBUSB_ERROR_IO;
|
|
361
|
-
} else if (config->bNumInterfaces > USB_MAXINTERFACES) {
|
|
362
|
-
usbi_err(ctx, "too many interfaces (%u)", config->bNumInterfaces);
|
|
363
|
-
return LIBUSB_ERROR_IO;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
usb_interface = calloc(config->bNumInterfaces, sizeof(*usb_interface));
|
|
367
|
-
if (!usb_interface)
|
|
368
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
369
|
-
|
|
370
|
-
config->interface = usb_interface;
|
|
371
|
-
|
|
372
|
-
buffer += config->bLength;
|
|
373
|
-
size -= config->bLength;
|
|
374
|
-
|
|
375
|
-
for (i = 0; i < config->bNumInterfaces; i++) {
|
|
376
|
-
const uint8_t *begin;
|
|
377
|
-
|
|
378
|
-
/* Skip over the rest of the Class Specific or Vendor */
|
|
379
|
-
/* Specific descriptors */
|
|
380
|
-
begin = buffer;
|
|
381
|
-
while (size >= DESC_HEADER_LENGTH) {
|
|
382
|
-
header = (const struct usbi_descriptor_header *)buffer;
|
|
383
|
-
if (header->bLength < DESC_HEADER_LENGTH) {
|
|
384
|
-
usbi_err(ctx,
|
|
385
|
-
"invalid extra config desc len (%u)",
|
|
386
|
-
header->bLength);
|
|
387
|
-
r = LIBUSB_ERROR_IO;
|
|
388
|
-
goto err;
|
|
389
|
-
} else if (header->bLength > size) {
|
|
390
|
-
usbi_warn(ctx,
|
|
391
|
-
"short extra config desc read %d/%u",
|
|
392
|
-
size, header->bLength);
|
|
393
|
-
config->bNumInterfaces = i;
|
|
394
|
-
return size;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/* If we find another "proper" descriptor then we're done */
|
|
398
|
-
if (header->bDescriptorType == LIBUSB_DT_ENDPOINT ||
|
|
399
|
-
header->bDescriptorType == LIBUSB_DT_INTERFACE ||
|
|
400
|
-
header->bDescriptorType == LIBUSB_DT_CONFIG ||
|
|
401
|
-
header->bDescriptorType == LIBUSB_DT_DEVICE)
|
|
402
|
-
break;
|
|
403
|
-
|
|
404
|
-
usbi_dbg(ctx, "skipping descriptor 0x%x", header->bDescriptorType);
|
|
405
|
-
buffer += header->bLength;
|
|
406
|
-
size -= header->bLength;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
/* Copy any unknown descriptors into a storage area for */
|
|
410
|
-
/* drivers to later parse */
|
|
411
|
-
ptrdiff_t len = buffer - begin;
|
|
412
|
-
if (len > 0) {
|
|
413
|
-
uint8_t *extra = realloc((void *)config->extra,
|
|
414
|
-
(size_t)(config->extra_length) + (size_t)len);
|
|
415
|
-
|
|
416
|
-
if (!extra) {
|
|
417
|
-
r = LIBUSB_ERROR_NO_MEM;
|
|
418
|
-
goto err;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
memcpy(extra + config->extra_length, begin, (size_t)len);
|
|
422
|
-
config->extra = extra;
|
|
423
|
-
config->extra_length += (int)len;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
r = parse_interface(ctx, usb_interface + i, buffer, (int)size);
|
|
427
|
-
if (r < 0)
|
|
428
|
-
goto err;
|
|
429
|
-
if (r == 0) {
|
|
430
|
-
config->bNumInterfaces = i;
|
|
431
|
-
break;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
buffer += r;
|
|
435
|
-
size -= r;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
return size;
|
|
439
|
-
|
|
440
|
-
err:
|
|
441
|
-
clear_configuration(config);
|
|
442
|
-
return r;
|
|
443
|
-
}
|
|
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
|
-
{
|
|
448
|
-
struct libusb_config_descriptor *_config = calloc(1, sizeof(*_config));
|
|
449
|
-
int r;
|
|
450
|
-
|
|
451
|
-
if (!_config)
|
|
452
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
453
|
-
|
|
454
|
-
r = parse_configuration(ctx, _config, buf, size);
|
|
455
|
-
if (r < 0) {
|
|
456
|
-
usbi_err(ctx, "parse_configuration failed with error %d", r);
|
|
457
|
-
free(_config);
|
|
458
|
-
return r;
|
|
459
|
-
} else if (r > 0) {
|
|
460
|
-
usbi_warn(ctx, "still %d bytes of descriptor data left", r);
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
*config = _config;
|
|
464
|
-
return LIBUSB_SUCCESS;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
static int get_active_config_descriptor(struct libusb_device *dev,
|
|
468
|
-
uint8_t *buffer, size_t size)
|
|
469
|
-
{
|
|
470
|
-
int r = usbi_backend.get_active_config_descriptor(dev, buffer, size);
|
|
471
|
-
|
|
472
|
-
if (r < 0)
|
|
473
|
-
return r;
|
|
474
|
-
|
|
475
|
-
if (r < LIBUSB_DT_CONFIG_SIZE) {
|
|
476
|
-
usbi_err(DEVICE_CTX(dev), "short config descriptor read %d/%d",
|
|
477
|
-
r, LIBUSB_DT_CONFIG_SIZE);
|
|
478
|
-
return LIBUSB_ERROR_IO;
|
|
479
|
-
} else if (r != (int)size) {
|
|
480
|
-
usbi_warn(DEVICE_CTX(dev), "short config descriptor read %d/%d",
|
|
481
|
-
r, (int)size);
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
return r;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
static int get_config_descriptor(struct libusb_device *dev, uint8_t config_idx,
|
|
488
|
-
uint8_t *buffer, size_t size)
|
|
489
|
-
{
|
|
490
|
-
int r = usbi_backend.get_config_descriptor(dev, config_idx, buffer, size);
|
|
491
|
-
|
|
492
|
-
if (r < 0)
|
|
493
|
-
return r;
|
|
494
|
-
if (r < LIBUSB_DT_CONFIG_SIZE) {
|
|
495
|
-
usbi_err(DEVICE_CTX(dev), "short config descriptor read %d/%d",
|
|
496
|
-
r, LIBUSB_DT_CONFIG_SIZE);
|
|
497
|
-
return LIBUSB_ERROR_IO;
|
|
498
|
-
} else if (r != (int)size) {
|
|
499
|
-
usbi_warn(DEVICE_CTX(dev), "short config descriptor read %d/%d",
|
|
500
|
-
r, (int)size);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
return r;
|
|
504
|
-
}
|
|
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
|
-
{
|
|
521
|
-
usbi_dbg(DEVICE_CTX(dev), " ");
|
|
522
|
-
static_assert(sizeof(dev->device_descriptor) == LIBUSB_DT_DEVICE_SIZE,
|
|
523
|
-
"struct libusb_device_descriptor is not expected size");
|
|
524
|
-
*desc = dev->device_descriptor;
|
|
525
|
-
return 0;
|
|
526
|
-
}
|
|
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
|
-
{
|
|
545
|
-
union usbi_config_desc_buf _config;
|
|
546
|
-
uint16_t config_len;
|
|
547
|
-
uint8_t *buf;
|
|
548
|
-
int r;
|
|
549
|
-
|
|
550
|
-
r = get_active_config_descriptor(dev, _config.buf, sizeof(_config.buf));
|
|
551
|
-
if (r < 0)
|
|
552
|
-
return r;
|
|
553
|
-
|
|
554
|
-
config_len = libusb_le16_to_cpu(_config.desc.wTotalLength);
|
|
555
|
-
buf = malloc(config_len);
|
|
556
|
-
if (!buf)
|
|
557
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
558
|
-
|
|
559
|
-
r = get_active_config_descriptor(dev, buf, config_len);
|
|
560
|
-
if (r >= 0)
|
|
561
|
-
r = raw_desc_to_config(DEVICE_CTX(dev), buf, r, config);
|
|
562
|
-
|
|
563
|
-
free(buf);
|
|
564
|
-
return r;
|
|
565
|
-
}
|
|
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
|
-
{
|
|
586
|
-
union usbi_config_desc_buf _config;
|
|
587
|
-
uint16_t config_len;
|
|
588
|
-
uint8_t *buf;
|
|
589
|
-
int r;
|
|
590
|
-
|
|
591
|
-
usbi_dbg(DEVICE_CTX(dev), "index %u", config_index);
|
|
592
|
-
if (config_index >= dev->device_descriptor.bNumConfigurations)
|
|
593
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
|
594
|
-
|
|
595
|
-
r = get_config_descriptor(dev, config_index, _config.buf, sizeof(_config.buf));
|
|
596
|
-
if (r < 0)
|
|
597
|
-
return r;
|
|
598
|
-
|
|
599
|
-
config_len = libusb_le16_to_cpu(_config.desc.wTotalLength);
|
|
600
|
-
buf = malloc(config_len);
|
|
601
|
-
if (!buf)
|
|
602
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
603
|
-
|
|
604
|
-
r = get_config_descriptor(dev, config_index, buf, config_len);
|
|
605
|
-
if (r >= 0)
|
|
606
|
-
r = raw_desc_to_config(DEVICE_CTX(dev), buf, r, config);
|
|
607
|
-
|
|
608
|
-
free(buf);
|
|
609
|
-
return r;
|
|
610
|
-
}
|
|
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
|
-
{
|
|
632
|
-
uint8_t idx;
|
|
633
|
-
int r;
|
|
634
|
-
|
|
635
|
-
if (usbi_backend.get_config_descriptor_by_value) {
|
|
636
|
-
void *buf;
|
|
637
|
-
|
|
638
|
-
r = usbi_backend.get_config_descriptor_by_value(dev,
|
|
639
|
-
bConfigurationValue, &buf);
|
|
640
|
-
if (r < 0)
|
|
641
|
-
return r;
|
|
642
|
-
|
|
643
|
-
return raw_desc_to_config(DEVICE_CTX(dev), buf, r, config);
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
usbi_dbg(DEVICE_CTX(dev), "value %u", bConfigurationValue);
|
|
647
|
-
for (idx = 0; idx < dev->device_descriptor.bNumConfigurations; idx++) {
|
|
648
|
-
union usbi_config_desc_buf _config;
|
|
649
|
-
|
|
650
|
-
r = get_config_descriptor(dev, idx, _config.buf, sizeof(_config.buf));
|
|
651
|
-
if (r < 0)
|
|
652
|
-
return r;
|
|
653
|
-
|
|
654
|
-
if (_config.desc.bConfigurationValue == bConfigurationValue)
|
|
655
|
-
return libusb_get_config_descriptor(dev, idx, config);
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
|
659
|
-
}
|
|
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
|
-
{
|
|
672
|
-
if (!config)
|
|
673
|
-
return;
|
|
674
|
-
|
|
675
|
-
clear_configuration(config);
|
|
676
|
-
free(config);
|
|
677
|
-
}
|
|
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
|
-
{
|
|
697
|
-
const struct usbi_descriptor_header *header;
|
|
698
|
-
const uint8_t *buffer = endpoint->extra;
|
|
699
|
-
int size = endpoint->extra_length;
|
|
700
|
-
|
|
701
|
-
*ep_comp = NULL;
|
|
702
|
-
|
|
703
|
-
while (size >= DESC_HEADER_LENGTH) {
|
|
704
|
-
header = (const struct usbi_descriptor_header *)buffer;
|
|
705
|
-
if (header->bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMPANION) {
|
|
706
|
-
if (header->bLength < DESC_HEADER_LENGTH) {
|
|
707
|
-
usbi_err(ctx, "invalid descriptor length %u",
|
|
708
|
-
header->bLength);
|
|
709
|
-
return LIBUSB_ERROR_IO;
|
|
710
|
-
}
|
|
711
|
-
buffer += header->bLength;
|
|
712
|
-
size -= header->bLength;
|
|
713
|
-
continue;
|
|
714
|
-
} else if (header->bLength < LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE) {
|
|
715
|
-
usbi_err(ctx, "invalid ss-ep-comp-desc length %u",
|
|
716
|
-
header->bLength);
|
|
717
|
-
return LIBUSB_ERROR_IO;
|
|
718
|
-
} else if (header->bLength > size) {
|
|
719
|
-
usbi_err(ctx, "short ss-ep-comp-desc read %d/%u",
|
|
720
|
-
size, header->bLength);
|
|
721
|
-
return LIBUSB_ERROR_IO;
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
*ep_comp = malloc(sizeof(**ep_comp));
|
|
725
|
-
if (!*ep_comp)
|
|
726
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
727
|
-
(*ep_comp)->bLength = buffer[0];
|
|
728
|
-
(*ep_comp)->bDescriptorType = buffer[1];
|
|
729
|
-
(*ep_comp)->bMaxBurst = buffer[2];
|
|
730
|
-
(*ep_comp)->bmAttributes = buffer[3];
|
|
731
|
-
(*ep_comp)->wBytesPerInterval = ReadLittleEndian16(&buffer[4]);
|
|
732
|
-
return LIBUSB_SUCCESS;
|
|
733
|
-
}
|
|
734
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
|
735
|
-
}
|
|
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
|
-
{
|
|
748
|
-
free(ep_comp);
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
static int parse_bos(struct libusb_context *ctx,
|
|
752
|
-
struct libusb_bos_descriptor **bos,
|
|
753
|
-
const uint8_t *buffer, int size)
|
|
754
|
-
{
|
|
755
|
-
struct libusb_bos_descriptor *_bos;
|
|
756
|
-
const struct usbi_bos_descriptor *bos_desc;
|
|
757
|
-
const struct usbi_descriptor_header *header;
|
|
758
|
-
uint8_t i;
|
|
759
|
-
|
|
760
|
-
if (size < LIBUSB_DT_BOS_SIZE) {
|
|
761
|
-
usbi_err(ctx, "short bos descriptor read %d/%d",
|
|
762
|
-
size, LIBUSB_DT_BOS_SIZE);
|
|
763
|
-
return LIBUSB_ERROR_IO;
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
bos_desc = (const struct usbi_bos_descriptor *)buffer;
|
|
767
|
-
if (bos_desc->bDescriptorType != LIBUSB_DT_BOS) {
|
|
768
|
-
usbi_err(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
|
|
769
|
-
bos_desc->bDescriptorType, LIBUSB_DT_BOS);
|
|
770
|
-
return LIBUSB_ERROR_IO;
|
|
771
|
-
} else if (bos_desc->bLength < LIBUSB_DT_BOS_SIZE) {
|
|
772
|
-
usbi_err(ctx, "invalid bos bLength (%u)", bos_desc->bLength);
|
|
773
|
-
return LIBUSB_ERROR_IO;
|
|
774
|
-
} else if (bos_desc->bLength > size) {
|
|
775
|
-
usbi_err(ctx, "short bos descriptor read %d/%u",
|
|
776
|
-
size, bos_desc->bLength);
|
|
777
|
-
return LIBUSB_ERROR_IO;
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
_bos = calloc(1, sizeof(*_bos) + bos_desc->bNumDeviceCaps * sizeof(void *));
|
|
781
|
-
if (!_bos)
|
|
782
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
783
|
-
|
|
784
|
-
_bos->bLength = buffer[0];
|
|
785
|
-
_bos->bDescriptorType = buffer[1];
|
|
786
|
-
_bos->wTotalLength = ReadLittleEndian16(&buffer[2]);
|
|
787
|
-
_bos->bNumDeviceCaps = buffer[4];
|
|
788
|
-
buffer += _bos->bLength;
|
|
789
|
-
size -= _bos->bLength;
|
|
790
|
-
|
|
791
|
-
/* Get the device capability descriptors */
|
|
792
|
-
for (i = 0; i < _bos->bNumDeviceCaps; i++) {
|
|
793
|
-
if (size < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) {
|
|
794
|
-
usbi_warn(ctx, "short dev-cap descriptor read %d/%d",
|
|
795
|
-
size, LIBUSB_DT_DEVICE_CAPABILITY_SIZE);
|
|
796
|
-
break;
|
|
797
|
-
}
|
|
798
|
-
header = (const struct usbi_descriptor_header *)buffer;
|
|
799
|
-
if (header->bDescriptorType != LIBUSB_DT_DEVICE_CAPABILITY) {
|
|
800
|
-
usbi_warn(ctx, "unexpected descriptor 0x%x (expected 0x%x)",
|
|
801
|
-
header->bDescriptorType, LIBUSB_DT_DEVICE_CAPABILITY);
|
|
802
|
-
break;
|
|
803
|
-
} else if (header->bLength < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) {
|
|
804
|
-
usbi_err(ctx, "invalid dev-cap bLength (%u)",
|
|
805
|
-
header->bLength);
|
|
806
|
-
libusb_free_bos_descriptor(_bos);
|
|
807
|
-
return LIBUSB_ERROR_IO;
|
|
808
|
-
} else if (header->bLength > size) {
|
|
809
|
-
usbi_warn(ctx, "short dev-cap descriptor read %d/%u",
|
|
810
|
-
size, header->bLength);
|
|
811
|
-
break;
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
_bos->dev_capability[i] = malloc(header->bLength);
|
|
815
|
-
if (!_bos->dev_capability[i]) {
|
|
816
|
-
libusb_free_bos_descriptor(_bos);
|
|
817
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
818
|
-
}
|
|
819
|
-
memcpy(_bos->dev_capability[i], buffer, header->bLength);
|
|
820
|
-
buffer += header->bLength;
|
|
821
|
-
size -= header->bLength;
|
|
822
|
-
}
|
|
823
|
-
_bos->bNumDeviceCaps = i;
|
|
824
|
-
*bos = _bos;
|
|
825
|
-
|
|
826
|
-
return LIBUSB_SUCCESS;
|
|
827
|
-
}
|
|
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
|
-
{
|
|
843
|
-
union usbi_bos_desc_buf _bos;
|
|
844
|
-
uint16_t bos_len;
|
|
845
|
-
uint8_t *bos_data;
|
|
846
|
-
int r;
|
|
847
|
-
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
|
-
r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, _bos.buf, sizeof(_bos.buf));
|
|
852
|
-
if (r < 0) {
|
|
853
|
-
if (r != LIBUSB_ERROR_PIPE)
|
|
854
|
-
usbi_err(ctx, "failed to read BOS (%d)", r);
|
|
855
|
-
return r;
|
|
856
|
-
}
|
|
857
|
-
if (r < LIBUSB_DT_BOS_SIZE) {
|
|
858
|
-
usbi_err(ctx, "short BOS read %d/%d",
|
|
859
|
-
r, LIBUSB_DT_BOS_SIZE);
|
|
860
|
-
return LIBUSB_ERROR_IO;
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
bos_len = libusb_le16_to_cpu(_bos.desc.wTotalLength);
|
|
864
|
-
usbi_dbg(ctx, "found BOS descriptor: size %u bytes, %u capabilities",
|
|
865
|
-
bos_len, _bos.desc.bNumDeviceCaps);
|
|
866
|
-
bos_data = calloc(1, bos_len);
|
|
867
|
-
if (!bos_data)
|
|
868
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
869
|
-
|
|
870
|
-
r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_data, bos_len);
|
|
871
|
-
if (r >= 0) {
|
|
872
|
-
if (r != (int)bos_len)
|
|
873
|
-
usbi_warn(ctx, "short BOS read %d/%u", r, bos_len);
|
|
874
|
-
r = parse_bos(HANDLE_CTX(dev_handle), bos, bos_data, r);
|
|
875
|
-
} else {
|
|
876
|
-
usbi_err(ctx, "failed to read BOS (%d)", r);
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
free(bos_data);
|
|
880
|
-
return r;
|
|
881
|
-
}
|
|
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
|
-
{
|
|
892
|
-
uint8_t i;
|
|
893
|
-
|
|
894
|
-
if (!bos)
|
|
895
|
-
return;
|
|
896
|
-
|
|
897
|
-
for (i = 0; i < bos->bNumDeviceCaps; i++)
|
|
898
|
-
free(bos->dev_capability[i]);
|
|
899
|
-
free(bos);
|
|
900
|
-
}
|
|
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
|
-
{
|
|
920
|
-
struct libusb_usb_2_0_extension_descriptor *_usb_2_0_extension;
|
|
921
|
-
|
|
922
|
-
if (dev_cap->bDevCapabilityType != LIBUSB_BT_USB_2_0_EXTENSION) {
|
|
923
|
-
usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
|
|
924
|
-
dev_cap->bDevCapabilityType,
|
|
925
|
-
LIBUSB_BT_USB_2_0_EXTENSION);
|
|
926
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
|
927
|
-
} else if (dev_cap->bLength < LIBUSB_BT_USB_2_0_EXTENSION_SIZE) {
|
|
928
|
-
usbi_err(ctx, "short dev-cap descriptor read %u/%d",
|
|
929
|
-
dev_cap->bLength, LIBUSB_BT_USB_2_0_EXTENSION_SIZE);
|
|
930
|
-
return LIBUSB_ERROR_IO;
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
_usb_2_0_extension = malloc(sizeof(*_usb_2_0_extension));
|
|
934
|
-
if (!_usb_2_0_extension)
|
|
935
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
936
|
-
|
|
937
|
-
_usb_2_0_extension->bLength = dev_cap->bLength;
|
|
938
|
-
_usb_2_0_extension->bDescriptorType = dev_cap->bDescriptorType;
|
|
939
|
-
_usb_2_0_extension->bDevCapabilityType = dev_cap->bDevCapabilityType;
|
|
940
|
-
_usb_2_0_extension->bmAttributes = ReadLittleEndian32(dev_cap->dev_capability_data);
|
|
941
|
-
|
|
942
|
-
*usb_2_0_extension = _usb_2_0_extension;
|
|
943
|
-
return LIBUSB_SUCCESS;
|
|
944
|
-
}
|
|
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
|
-
{
|
|
957
|
-
free(usb_2_0_extension);
|
|
958
|
-
}
|
|
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
|
-
{
|
|
978
|
-
struct libusb_ss_usb_device_capability_descriptor *_ss_usb_device_cap;
|
|
979
|
-
|
|
980
|
-
if (dev_cap->bDevCapabilityType != LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) {
|
|
981
|
-
usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
|
|
982
|
-
dev_cap->bDevCapabilityType,
|
|
983
|
-
LIBUSB_BT_SS_USB_DEVICE_CAPABILITY);
|
|
984
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
|
985
|
-
} else if (dev_cap->bLength < LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) {
|
|
986
|
-
usbi_err(ctx, "short dev-cap descriptor read %u/%d",
|
|
987
|
-
dev_cap->bLength, LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE);
|
|
988
|
-
return LIBUSB_ERROR_IO;
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
_ss_usb_device_cap = malloc(sizeof(*_ss_usb_device_cap));
|
|
992
|
-
if (!_ss_usb_device_cap)
|
|
993
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
994
|
-
|
|
995
|
-
_ss_usb_device_cap->bLength = dev_cap->bLength;
|
|
996
|
-
_ss_usb_device_cap->bDescriptorType = dev_cap->bDescriptorType;
|
|
997
|
-
_ss_usb_device_cap->bDevCapabilityType = dev_cap->bDevCapabilityType;
|
|
998
|
-
_ss_usb_device_cap->bmAttributes = dev_cap->dev_capability_data[0];
|
|
999
|
-
_ss_usb_device_cap->wSpeedSupported = ReadLittleEndian16(&dev_cap->dev_capability_data[1]);
|
|
1000
|
-
_ss_usb_device_cap->bFunctionalitySupport = dev_cap->dev_capability_data[3];
|
|
1001
|
-
_ss_usb_device_cap->bU1DevExitLat = dev_cap->dev_capability_data[4];
|
|
1002
|
-
_ss_usb_device_cap->bU2DevExitLat = ReadLittleEndian16(&dev_cap->dev_capability_data[5]);
|
|
1003
|
-
|
|
1004
|
-
*ss_usb_device_cap = _ss_usb_device_cap;
|
|
1005
|
-
return LIBUSB_SUCCESS;
|
|
1006
|
-
}
|
|
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
|
-
/** \ingroup libusb_desc
|
|
1039
|
-
* Get a SuperSpeedPlus USB Device Capability descriptor
|
|
1040
|
-
*
|
|
1041
|
-
* Since version 1.0.28, \ref LIBUSB_API_VERSION >= 0x0100010B
|
|
1042
|
-
*
|
|
1043
|
-
* \param ctx the context to operate on, or NULL for the default context
|
|
1044
|
-
* \param dev_cap Device Capability descriptor with a bDevCapabilityType of
|
|
1045
|
-
* \ref libusb_bos_type::LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY
|
|
1046
|
-
* LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY
|
|
1047
|
-
* \param ssplus_usb_device_cap output location for the SuperSpeedPlus USB Device
|
|
1048
|
-
* Capability descriptor. Only valid if 0 was returned. Must be freed with
|
|
1049
|
-
* libusb_free_ssplus_usb_device_capability_descriptor() after use.
|
|
1050
|
-
* \returns 0 on success
|
|
1051
|
-
* \returns a LIBUSB_ERROR code on error
|
|
1052
|
-
*/
|
|
1053
|
-
int API_EXPORTED libusb_get_ssplus_usb_device_capability_descriptor(
|
|
1054
|
-
libusb_context *ctx,
|
|
1055
|
-
struct libusb_bos_dev_capability_descriptor *dev_cap,
|
|
1056
|
-
struct libusb_ssplus_usb_device_capability_descriptor **ssplus_usb_device_cap)
|
|
1057
|
-
{
|
|
1058
|
-
struct libusb_ssplus_usb_device_capability_descriptor *_ssplus_cap;
|
|
1059
|
-
|
|
1060
|
-
/* Use a private struct to reuse our descriptor parsing system. */
|
|
1061
|
-
struct internal_ssplus_capability_descriptor parsedDescriptor;
|
|
1062
|
-
|
|
1063
|
-
/* Some size/type checks to make sure everything is in order */
|
|
1064
|
-
if (dev_cap->bDevCapabilityType != LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY) {
|
|
1065
|
-
usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
|
|
1066
|
-
dev_cap->bDevCapabilityType,
|
|
1067
|
-
LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY);
|
|
1068
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
|
1069
|
-
} else if (dev_cap->bLength < LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE) {
|
|
1070
|
-
usbi_err(ctx, "short dev-cap descriptor read %u/%d",
|
|
1071
|
-
dev_cap->bLength, LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE);
|
|
1072
|
-
return LIBUSB_ERROR_IO;
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
const uint8_t* dev_capability_data = dev_cap->dev_capability_data;
|
|
1076
|
-
parsedDescriptor.bLength = dev_cap->bLength;
|
|
1077
|
-
parsedDescriptor.bDescriptorType = dev_cap->bDescriptorType;
|
|
1078
|
-
parsedDescriptor.bDevCapabilityType = dev_cap->bDevCapabilityType;
|
|
1079
|
-
parsedDescriptor.bReserved = dev_capability_data[0];
|
|
1080
|
-
parsedDescriptor.bmAttributes = ReadLittleEndian32(&dev_capability_data[1]);
|
|
1081
|
-
parsedDescriptor.wFunctionalitySupport = ReadLittleEndian16(&dev_capability_data[5]);
|
|
1082
|
-
parsedDescriptor.wReserved = ReadLittleEndian16(&dev_capability_data[7]);
|
|
1083
|
-
|
|
1084
|
-
uint8_t numSublikSpeedAttributes = (parsedDescriptor.bmAttributes & 0xF) + 1;
|
|
1085
|
-
_ssplus_cap = malloc(sizeof(struct libusb_ssplus_usb_device_capability_descriptor) + numSublikSpeedAttributes * sizeof(struct libusb_ssplus_sublink_attribute));
|
|
1086
|
-
if (!_ssplus_cap)
|
|
1087
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
1088
|
-
|
|
1089
|
-
/* Parse bmAttributes */
|
|
1090
|
-
_ssplus_cap->numSublinkSpeedAttributes = numSublikSpeedAttributes;
|
|
1091
|
-
_ssplus_cap->numSublinkSpeedIDs = ((parsedDescriptor.bmAttributes & 0xF0) >> 4) + 1;
|
|
1092
|
-
|
|
1093
|
-
/* Parse wFunctionalitySupport */
|
|
1094
|
-
_ssplus_cap->ssid = parsedDescriptor.wFunctionalitySupport & 0xF;
|
|
1095
|
-
_ssplus_cap->minRxLaneCount = (parsedDescriptor.wFunctionalitySupport & 0x0F00) >> 8;
|
|
1096
|
-
_ssplus_cap->minTxLaneCount = (parsedDescriptor.wFunctionalitySupport & 0xF000) >> 12;
|
|
1097
|
-
|
|
1098
|
-
/* Check that we have enough to read all the sublink attributes */
|
|
1099
|
-
if (dev_cap->bLength < LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE + _ssplus_cap->numSublinkSpeedAttributes * sizeof(uint32_t)) {
|
|
1100
|
-
usbi_err(ctx, "short ssplus capability descriptor, unable to read sublinks: Not enough data");
|
|
1101
|
-
return LIBUSB_ERROR_IO;
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
/* Read the attributes */
|
|
1105
|
-
uint8_t* base = ((uint8_t*)dev_cap) + LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE;
|
|
1106
|
-
for(uint8_t i = 0 ; i < _ssplus_cap->numSublinkSpeedAttributes ; i++) {
|
|
1107
|
-
uint32_t attr = ReadLittleEndian32(base + i * sizeof(uint32_t));
|
|
1108
|
-
_ssplus_cap->sublinkSpeedAttributes[i].ssid = attr & 0x0f;
|
|
1109
|
-
_ssplus_cap->sublinkSpeedAttributes[i].mantissa = attr >> 16;
|
|
1110
|
-
_ssplus_cap->sublinkSpeedAttributes[i].exponent = (attr >> 4) & 0x3 ;
|
|
1111
|
-
_ssplus_cap->sublinkSpeedAttributes[i].type = attr & 0x40 ? LIBUSB_SSPLUS_ATTR_TYPE_ASYM : LIBUSB_SSPLUS_ATTR_TYPE_SYM;
|
|
1112
|
-
_ssplus_cap->sublinkSpeedAttributes[i].direction = attr & 0x80 ? LIBUSB_SSPLUS_ATTR_DIR_TX : LIBUSB_SSPLUS_ATTR_DIR_RX;
|
|
1113
|
-
_ssplus_cap->sublinkSpeedAttributes[i].protocol = attr & 0x4000 ? LIBUSB_SSPLUS_ATTR_PROT_SSPLUS: LIBUSB_SSPLUS_ATTR_PROT_SS;
|
|
1114
|
-
}
|
|
1115
|
-
|
|
1116
|
-
*ssplus_usb_device_cap = _ssplus_cap;
|
|
1117
|
-
return LIBUSB_SUCCESS;
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
/** \ingroup libusb_desc
|
|
1121
|
-
* Free a SuperSpeedPlus USB Device Capability descriptor obtained from
|
|
1122
|
-
* libusb_get_ssplus_usb_device_capability_descriptor().
|
|
1123
|
-
* It is safe to call this function with a NULL ssplus_usb_device_cap
|
|
1124
|
-
* parameter, in which case the function simply returns.
|
|
1125
|
-
*
|
|
1126
|
-
* Since version 1.0.28, \ref LIBUSB_API_VERSION >= 0x0100010B
|
|
1127
|
-
*
|
|
1128
|
-
* \param ssplus_usb_device_cap the SuperSpeedPlus USB Device Capability descriptor
|
|
1129
|
-
* to free
|
|
1130
|
-
*/
|
|
1131
|
-
void API_EXPORTED libusb_free_ssplus_usb_device_capability_descriptor(
|
|
1132
|
-
struct libusb_ssplus_usb_device_capability_descriptor *ssplus_usb_device_cap)
|
|
1133
|
-
{
|
|
1134
|
-
free(ssplus_usb_device_cap);
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
/** \ingroup libusb_desc
|
|
1140
|
-
* Free a SuperSpeed USB Device Capability descriptor obtained from
|
|
1141
|
-
* libusb_get_ss_usb_device_capability_descriptor().
|
|
1142
|
-
* It is safe to call this function with a NULL ss_usb_device_cap
|
|
1143
|
-
* parameter, in which case the function simply returns.
|
|
1144
|
-
*
|
|
1145
|
-
* \param ss_usb_device_cap the SuperSpeed USB Device Capability descriptor
|
|
1146
|
-
* to free
|
|
1147
|
-
*/
|
|
1148
|
-
void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor(
|
|
1149
|
-
struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap)
|
|
1150
|
-
{
|
|
1151
|
-
free(ss_usb_device_cap);
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
|
-
/** \ingroup libusb_desc
|
|
1155
|
-
* Get a Container ID descriptor
|
|
1156
|
-
*
|
|
1157
|
-
* \param ctx the context to operate on, or NULL for the default context
|
|
1158
|
-
* \param dev_cap Device Capability descriptor with a bDevCapabilityType of
|
|
1159
|
-
* \ref libusb_bos_type::LIBUSB_BT_CONTAINER_ID
|
|
1160
|
-
* LIBUSB_BT_CONTAINER_ID
|
|
1161
|
-
* \param container_id output location for the Container ID descriptor.
|
|
1162
|
-
* Only valid if 0 was returned. Must be freed with
|
|
1163
|
-
* libusb_free_container_id_descriptor() after use.
|
|
1164
|
-
* \returns 0 on success
|
|
1165
|
-
* \returns a LIBUSB_ERROR code on error
|
|
1166
|
-
*/
|
|
1167
|
-
int API_EXPORTED libusb_get_container_id_descriptor(libusb_context *ctx,
|
|
1168
|
-
struct libusb_bos_dev_capability_descriptor *dev_cap,
|
|
1169
|
-
struct libusb_container_id_descriptor **container_id)
|
|
1170
|
-
{
|
|
1171
|
-
struct libusb_container_id_descriptor *_container_id;
|
|
1172
|
-
|
|
1173
|
-
if (dev_cap->bDevCapabilityType != LIBUSB_BT_CONTAINER_ID) {
|
|
1174
|
-
usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
|
|
1175
|
-
dev_cap->bDevCapabilityType,
|
|
1176
|
-
LIBUSB_BT_CONTAINER_ID);
|
|
1177
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
|
1178
|
-
} else if (dev_cap->bLength < LIBUSB_BT_CONTAINER_ID_SIZE) {
|
|
1179
|
-
usbi_err(ctx, "short dev-cap descriptor read %u/%d",
|
|
1180
|
-
dev_cap->bLength, LIBUSB_BT_CONTAINER_ID_SIZE);
|
|
1181
|
-
return LIBUSB_ERROR_IO;
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
_container_id = malloc(sizeof(*_container_id));
|
|
1185
|
-
if (!_container_id)
|
|
1186
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
1187
|
-
|
|
1188
|
-
_container_id->bLength = dev_cap->bLength;
|
|
1189
|
-
_container_id->bDescriptorType = dev_cap->bDescriptorType;
|
|
1190
|
-
_container_id->bDevCapabilityType = dev_cap->bDevCapabilityType;
|
|
1191
|
-
_container_id->bReserved = dev_cap->dev_capability_data[0];
|
|
1192
|
-
memcpy(_container_id->ContainerID, &dev_cap->dev_capability_data[1], 16);
|
|
1193
|
-
|
|
1194
|
-
*container_id = _container_id;
|
|
1195
|
-
return LIBUSB_SUCCESS;
|
|
1196
|
-
}
|
|
1197
|
-
|
|
1198
|
-
/** \ingroup libusb_desc
|
|
1199
|
-
* Free a Container ID descriptor obtained from
|
|
1200
|
-
* libusb_get_container_id_descriptor().
|
|
1201
|
-
* It is safe to call this function with a NULL container_id parameter,
|
|
1202
|
-
* in which case the function simply returns.
|
|
1203
|
-
*
|
|
1204
|
-
* \param container_id the Container ID descriptor to free
|
|
1205
|
-
*/
|
|
1206
|
-
void API_EXPORTED libusb_free_container_id_descriptor(
|
|
1207
|
-
struct libusb_container_id_descriptor *container_id)
|
|
1208
|
-
{
|
|
1209
|
-
free(container_id);
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
/** \ingroup libusb_desc
|
|
1213
|
-
* Get a platform descriptor
|
|
1214
|
-
*
|
|
1215
|
-
* Since version 1.0.27, \ref LIBUSB_API_VERSION >= 0x0100010A
|
|
1216
|
-
*
|
|
1217
|
-
* \param ctx the context to operate on, or NULL for the default context
|
|
1218
|
-
* \param dev_cap Device Capability descriptor with a bDevCapabilityType of
|
|
1219
|
-
* \ref libusb_bos_type::LIBUSB_BT_PLATFORM_DESCRIPTOR
|
|
1220
|
-
* LIBUSB_BT_PLATFORM_DESCRIPTOR
|
|
1221
|
-
* \param platform_descriptor output location for the Platform descriptor.
|
|
1222
|
-
* Only valid if 0 was returned. Must be freed with
|
|
1223
|
-
* libusb_free_platform_descriptor() after use.
|
|
1224
|
-
* \returns 0 on success
|
|
1225
|
-
* \returns a LIBUSB_ERROR code on error
|
|
1226
|
-
*/
|
|
1227
|
-
int API_EXPORTED libusb_get_platform_descriptor(libusb_context *ctx,
|
|
1228
|
-
struct libusb_bos_dev_capability_descriptor *dev_cap,
|
|
1229
|
-
struct libusb_platform_descriptor **platform_descriptor)
|
|
1230
|
-
{
|
|
1231
|
-
struct libusb_platform_descriptor *_platform_descriptor;
|
|
1232
|
-
|
|
1233
|
-
if (dev_cap->bDevCapabilityType != LIBUSB_BT_PLATFORM_DESCRIPTOR) {
|
|
1234
|
-
usbi_err(ctx, "unexpected bDevCapabilityType 0x%x (expected 0x%x)",
|
|
1235
|
-
dev_cap->bDevCapabilityType,
|
|
1236
|
-
LIBUSB_BT_PLATFORM_DESCRIPTOR);
|
|
1237
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
|
1238
|
-
} else if (dev_cap->bLength < LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE) {
|
|
1239
|
-
usbi_err(ctx, "short dev-cap descriptor read %u/%d",
|
|
1240
|
-
dev_cap->bLength, LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE);
|
|
1241
|
-
return LIBUSB_ERROR_IO;
|
|
1242
|
-
}
|
|
1243
|
-
|
|
1244
|
-
_platform_descriptor = malloc(dev_cap->bLength);
|
|
1245
|
-
if (!_platform_descriptor)
|
|
1246
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
1247
|
-
|
|
1248
|
-
_platform_descriptor->bLength = dev_cap->bLength;
|
|
1249
|
-
_platform_descriptor->bDescriptorType = dev_cap->bDescriptorType;
|
|
1250
|
-
_platform_descriptor->bDevCapabilityType = dev_cap->bDevCapabilityType;
|
|
1251
|
-
_platform_descriptor->bReserved = dev_cap->dev_capability_data[0];
|
|
1252
|
-
memcpy(_platform_descriptor->PlatformCapabilityUUID, &(dev_cap->dev_capability_data[1]), 16);
|
|
1253
|
-
|
|
1254
|
-
/* Capability data is located after reserved byte and 16 byte UUID */
|
|
1255
|
-
uint8_t* capability_data = dev_cap->dev_capability_data + 1 + 16;
|
|
1256
|
-
|
|
1257
|
-
/* Capability data length is total descriptor length minus initial fields */
|
|
1258
|
-
size_t capability_data_length = dev_cap->bLength - (3 + 1 + 16);
|
|
1259
|
-
|
|
1260
|
-
memcpy(_platform_descriptor->CapabilityData, capability_data, capability_data_length);
|
|
1261
|
-
|
|
1262
|
-
*platform_descriptor = _platform_descriptor;
|
|
1263
|
-
return LIBUSB_SUCCESS;
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
/** \ingroup libusb_desc
|
|
1267
|
-
* Free a platform descriptor obtained from
|
|
1268
|
-
* libusb_get_platform_descriptor().
|
|
1269
|
-
* It is safe to call this function with a NULL platform_descriptor parameter,
|
|
1270
|
-
* in which case the function simply returns.
|
|
1271
|
-
*
|
|
1272
|
-
* \param platform_descriptor the Platform descriptor to free
|
|
1273
|
-
*/
|
|
1274
|
-
void API_EXPORTED libusb_free_platform_descriptor(
|
|
1275
|
-
struct libusb_platform_descriptor *platform_descriptor)
|
|
1276
|
-
{
|
|
1277
|
-
free(platform_descriptor);
|
|
1278
|
-
}
|
|
1279
|
-
|
|
1280
|
-
/** \ingroup libusb_desc
|
|
1281
|
-
* Retrieve a string descriptor in C style ASCII.
|
|
1282
|
-
*
|
|
1283
|
-
* Wrapper around libusb_get_string_descriptor(). Uses the first language
|
|
1284
|
-
* supported by the device.
|
|
1285
|
-
*
|
|
1286
|
-
* \param dev_handle a device handle
|
|
1287
|
-
* \param desc_index the index of the descriptor to retrieve
|
|
1288
|
-
* \param data output buffer for ASCII string descriptor
|
|
1289
|
-
* \param length size of data buffer
|
|
1290
|
-
* \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
|
|
1291
|
-
*/
|
|
1292
|
-
int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle,
|
|
1293
|
-
uint8_t desc_index, unsigned char *data, int length)
|
|
1294
|
-
{
|
|
1295
|
-
union usbi_string_desc_buf str;
|
|
1296
|
-
int r;
|
|
1297
|
-
uint16_t langid, wdata;
|
|
1298
|
-
|
|
1299
|
-
/* Asking for the zero'th index is special - it returns a string
|
|
1300
|
-
* descriptor that contains all the language IDs supported by the
|
|
1301
|
-
* device. Typically there aren't many - often only one. Language
|
|
1302
|
-
* IDs are 16 bit numbers, and they start at the third byte in the
|
|
1303
|
-
* descriptor. There's also no point in trying to read descriptor 0
|
|
1304
|
-
* with this function. See USB 2.0 specification section 9.6.7 for
|
|
1305
|
-
* more information.
|
|
1306
|
-
*/
|
|
1307
|
-
|
|
1308
|
-
if (desc_index == 0)
|
|
1309
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
|
1310
|
-
|
|
1311
|
-
r = libusb_get_string_descriptor(dev_handle, 0, 0, str.buf, 4);
|
|
1312
|
-
if (r < 0)
|
|
1313
|
-
return r;
|
|
1314
|
-
else if (r != 4 || str.desc.bLength < 4 || str.desc.bDescriptorType != LIBUSB_DT_STRING)
|
|
1315
|
-
return LIBUSB_ERROR_IO;
|
|
1316
|
-
else if (str.desc.bLength & 1)
|
|
1317
|
-
usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for language ID string descriptor", str.desc.bLength);
|
|
1318
|
-
|
|
1319
|
-
langid = libusb_le16_to_cpu(str.desc.wData[0]);
|
|
1320
|
-
r = libusb_get_string_descriptor(dev_handle, desc_index, langid, str.buf, sizeof(str.buf));
|
|
1321
|
-
if (r < 0)
|
|
1322
|
-
return r;
|
|
1323
|
-
else if (r < DESC_HEADER_LENGTH || str.desc.bLength > r || str.desc.bDescriptorType != LIBUSB_DT_STRING)
|
|
1324
|
-
return LIBUSB_ERROR_IO;
|
|
1325
|
-
else if ((str.desc.bLength & 1) || str.desc.bLength != r)
|
|
1326
|
-
usbi_warn(HANDLE_CTX(dev_handle), "suspicious bLength %u for string descriptor (read %d)", str.desc.bLength, r);
|
|
1327
|
-
|
|
1328
|
-
/* Stop one byte before the end to leave room for null termination. */
|
|
1329
|
-
int dest_max = length - 1;
|
|
1330
|
-
|
|
1331
|
-
/* The descriptor has this number of wide characters */
|
|
1332
|
-
int src_max = (str.desc.bLength - 1 - 1) / 2;
|
|
1333
|
-
|
|
1334
|
-
/* Neither read nor write more than the smallest buffer */
|
|
1335
|
-
int idx_max = MIN(dest_max, src_max);
|
|
1336
|
-
|
|
1337
|
-
int idx;
|
|
1338
|
-
for (idx = 0; idx < idx_max; ++idx) {
|
|
1339
|
-
wdata = libusb_le16_to_cpu(str.desc.wData[idx]);
|
|
1340
|
-
if (wdata < 0x80)
|
|
1341
|
-
data[idx] = (unsigned char)wdata;
|
|
1342
|
-
else
|
|
1343
|
-
data[idx] = '?'; /* non-ASCII */
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
data[idx] = 0; /* null-terminate string */
|
|
1347
|
-
return idx;
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
static int parse_iad_array(struct libusb_context *ctx,
|
|
1351
|
-
struct libusb_interface_association_descriptor_array *iad_array,
|
|
1352
|
-
const uint8_t *buffer, int size)
|
|
1353
|
-
{
|
|
1354
|
-
uint8_t i;
|
|
1355
|
-
struct usbi_descriptor_header header;
|
|
1356
|
-
int consumed = 0;
|
|
1357
|
-
const uint8_t *buf = buffer;
|
|
1358
|
-
struct libusb_interface_association_descriptor *iad;
|
|
1359
|
-
|
|
1360
|
-
if (size < LIBUSB_DT_CONFIG_SIZE) {
|
|
1361
|
-
usbi_err(ctx, "short config descriptor read %d/%d",
|
|
1362
|
-
size, LIBUSB_DT_CONFIG_SIZE);
|
|
1363
|
-
return LIBUSB_ERROR_IO;
|
|
1364
|
-
}
|
|
1365
|
-
|
|
1366
|
-
/* First pass: Iterate through desc list, count number of IADs */
|
|
1367
|
-
iad_array->length = 0;
|
|
1368
|
-
while (consumed < size) {
|
|
1369
|
-
header.bLength = buf[0];
|
|
1370
|
-
header.bDescriptorType = buf[1];
|
|
1371
|
-
if (header.bLength < DESC_HEADER_LENGTH) {
|
|
1372
|
-
usbi_err(ctx, "invalid descriptor bLength %d",
|
|
1373
|
-
header.bLength);
|
|
1374
|
-
return LIBUSB_ERROR_IO;
|
|
1375
|
-
}
|
|
1376
|
-
else if (header.bLength > size) {
|
|
1377
|
-
usbi_warn(ctx, "short config descriptor read %d/%u",
|
|
1378
|
-
size, header.bLength);
|
|
1379
|
-
return LIBUSB_ERROR_IO;
|
|
1380
|
-
}
|
|
1381
|
-
if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION)
|
|
1382
|
-
iad_array->length++;
|
|
1383
|
-
buf += header.bLength;
|
|
1384
|
-
consumed += header.bLength;
|
|
1385
|
-
}
|
|
1386
|
-
|
|
1387
|
-
iad_array->iad = NULL;
|
|
1388
|
-
if (iad_array->length > 0) {
|
|
1389
|
-
iad = calloc((size_t)iad_array->length, sizeof(*iad));
|
|
1390
|
-
if (!iad)
|
|
1391
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
1392
|
-
|
|
1393
|
-
iad_array->iad = iad;
|
|
1394
|
-
|
|
1395
|
-
/* Second pass: Iterate through desc list, fill IAD structures */
|
|
1396
|
-
int remaining = size;
|
|
1397
|
-
i = 0;
|
|
1398
|
-
do {
|
|
1399
|
-
header.bLength = buffer[0];
|
|
1400
|
-
header.bDescriptorType = buffer[1];
|
|
1401
|
-
if (header.bDescriptorType == LIBUSB_DT_INTERFACE_ASSOCIATION && (remaining >= LIBUSB_DT_INTERFACE_ASSOCIATION_SIZE)) {
|
|
1402
|
-
iad[i].bLength = buffer[0];
|
|
1403
|
-
iad[i].bDescriptorType = buffer[1];
|
|
1404
|
-
iad[i].bFirstInterface = buffer[2];
|
|
1405
|
-
iad[i].bInterfaceCount = buffer[3];
|
|
1406
|
-
iad[i].bFunctionClass = buffer[4];
|
|
1407
|
-
iad[i].bFunctionSubClass = buffer[5];
|
|
1408
|
-
iad[i].bFunctionProtocol = buffer[6];
|
|
1409
|
-
iad[i].iFunction = buffer[7];
|
|
1410
|
-
i++;
|
|
1411
|
-
}
|
|
1412
|
-
|
|
1413
|
-
remaining -= header.bLength;
|
|
1414
|
-
if (remaining < DESC_HEADER_LENGTH) {
|
|
1415
|
-
break;
|
|
1416
|
-
}
|
|
1417
|
-
buffer += header.bLength;
|
|
1418
|
-
} while (1);
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
|
-
return LIBUSB_SUCCESS;
|
|
1422
|
-
}
|
|
1423
|
-
|
|
1424
|
-
static int raw_desc_to_iad_array(struct libusb_context *ctx, const uint8_t *buf,
|
|
1425
|
-
int size, struct libusb_interface_association_descriptor_array **iad_array)
|
|
1426
|
-
{
|
|
1427
|
-
struct libusb_interface_association_descriptor_array *_iad_array
|
|
1428
|
-
= calloc(1, sizeof(*_iad_array));
|
|
1429
|
-
int r;
|
|
1430
|
-
|
|
1431
|
-
if (!_iad_array)
|
|
1432
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
1433
|
-
|
|
1434
|
-
r = parse_iad_array(ctx, _iad_array, buf, size);
|
|
1435
|
-
if (r < 0) {
|
|
1436
|
-
usbi_err(ctx, "parse_iad_array failed with error %d", r);
|
|
1437
|
-
free(_iad_array);
|
|
1438
|
-
return r;
|
|
1439
|
-
}
|
|
1440
|
-
|
|
1441
|
-
*iad_array = _iad_array;
|
|
1442
|
-
return LIBUSB_SUCCESS;
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
|
-
/** \ingroup libusb_desc
|
|
1446
|
-
* Get an array of interface association descriptors (IAD) for a given
|
|
1447
|
-
* configuration.
|
|
1448
|
-
* This is a non-blocking function which does not involve any requests being
|
|
1449
|
-
* sent to the device.
|
|
1450
|
-
*
|
|
1451
|
-
* \param dev a device
|
|
1452
|
-
* \param config_index the index of the configuration you wish to retrieve the
|
|
1453
|
-
* IADs for.
|
|
1454
|
-
* \param iad_array output location for the array of IADs. Only valid if 0 was
|
|
1455
|
-
* returned. Must be freed with libusb_free_interface_association_descriptors()
|
|
1456
|
-
* after use. It's possible that a given configuration contains no IADs. In this
|
|
1457
|
-
* case the iad_array is still output, but will have 'length' field set to 0, and
|
|
1458
|
-
* iad field set to NULL.
|
|
1459
|
-
* \returns 0 on success
|
|
1460
|
-
* \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
|
|
1461
|
-
* \returns another LIBUSB_ERROR code on error
|
|
1462
|
-
* \see libusb_get_active_interface_association_descriptors()
|
|
1463
|
-
*/
|
|
1464
|
-
int API_EXPORTED libusb_get_interface_association_descriptors(libusb_device *dev,
|
|
1465
|
-
uint8_t config_index, struct libusb_interface_association_descriptor_array **iad_array)
|
|
1466
|
-
{
|
|
1467
|
-
union usbi_config_desc_buf _config;
|
|
1468
|
-
uint16_t config_len;
|
|
1469
|
-
uint8_t *buf;
|
|
1470
|
-
int r;
|
|
1471
|
-
|
|
1472
|
-
if (!iad_array)
|
|
1473
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
|
1474
|
-
|
|
1475
|
-
usbi_dbg(DEVICE_CTX(dev), "IADs for config index %u", config_index);
|
|
1476
|
-
if (config_index >= dev->device_descriptor.bNumConfigurations)
|
|
1477
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
|
1478
|
-
|
|
1479
|
-
r = get_config_descriptor(dev, config_index, _config.buf, sizeof(_config.buf));
|
|
1480
|
-
if (r < 0)
|
|
1481
|
-
return r;
|
|
1482
|
-
|
|
1483
|
-
config_len = libusb_le16_to_cpu(_config.desc.wTotalLength);
|
|
1484
|
-
buf = malloc(config_len);
|
|
1485
|
-
if (!buf)
|
|
1486
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
1487
|
-
|
|
1488
|
-
r = get_config_descriptor(dev, config_index, buf, config_len);
|
|
1489
|
-
if (r >= 0)
|
|
1490
|
-
r = raw_desc_to_iad_array(DEVICE_CTX(dev), buf, r, iad_array);
|
|
1491
|
-
|
|
1492
|
-
free(buf);
|
|
1493
|
-
return r;
|
|
1494
|
-
}
|
|
1495
|
-
|
|
1496
|
-
/** \ingroup libusb_desc
|
|
1497
|
-
* Get an array of interface association descriptors (IAD) for the currently
|
|
1498
|
-
* active configuration.
|
|
1499
|
-
* This is a non-blocking function which does not involve any requests being
|
|
1500
|
-
* sent to the device.
|
|
1501
|
-
*
|
|
1502
|
-
* \param dev a device
|
|
1503
|
-
* \param iad_array output location for the array of IADs. Only valid if 0 was
|
|
1504
|
-
* returned. Must be freed with libusb_free_interface_association_descriptors()
|
|
1505
|
-
* after use. It's possible that a given configuration contains no IADs. In this
|
|
1506
|
-
* case the iad_array is still output, but will have 'length' field set to 0, and
|
|
1507
|
-
* iad field set to NULL.
|
|
1508
|
-
* \returns 0 on success
|
|
1509
|
-
* \returns LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state
|
|
1510
|
-
* \returns another LIBUSB_ERROR code on error
|
|
1511
|
-
* \see libusb_get_interface_association_descriptors
|
|
1512
|
-
*/
|
|
1513
|
-
int API_EXPORTED libusb_get_active_interface_association_descriptors(libusb_device *dev,
|
|
1514
|
-
struct libusb_interface_association_descriptor_array **iad_array)
|
|
1515
|
-
{
|
|
1516
|
-
union usbi_config_desc_buf _config;
|
|
1517
|
-
uint16_t config_len;
|
|
1518
|
-
uint8_t *buf;
|
|
1519
|
-
int r;
|
|
1520
|
-
|
|
1521
|
-
if (!iad_array)
|
|
1522
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
|
1523
|
-
|
|
1524
|
-
r = get_active_config_descriptor(dev, _config.buf, sizeof(_config.buf));
|
|
1525
|
-
if (r < 0)
|
|
1526
|
-
return r;
|
|
1527
|
-
|
|
1528
|
-
config_len = libusb_le16_to_cpu(_config.desc.wTotalLength);
|
|
1529
|
-
buf = malloc(config_len);
|
|
1530
|
-
if (!buf)
|
|
1531
|
-
return LIBUSB_ERROR_NO_MEM;
|
|
1532
|
-
|
|
1533
|
-
r = get_active_config_descriptor(dev, buf, config_len);
|
|
1534
|
-
if (r >= 0)
|
|
1535
|
-
r = raw_desc_to_iad_array(DEVICE_CTX(dev), buf, r, iad_array);
|
|
1536
|
-
free(buf);
|
|
1537
|
-
return r;
|
|
1538
|
-
}
|
|
1539
|
-
|
|
1540
|
-
/** \ingroup libusb_desc
|
|
1541
|
-
* Free an array of interface association descriptors (IADs) obtained from
|
|
1542
|
-
* libusb_get_interface_association_descriptors() or
|
|
1543
|
-
* libusb_get_active_interface_association_descriptors().
|
|
1544
|
-
* It is safe to call this function with a NULL iad_array parameter, in which
|
|
1545
|
-
* case the function simply returns.
|
|
1546
|
-
*
|
|
1547
|
-
* \param iad_array the IAD array to free
|
|
1548
|
-
*/
|
|
1549
|
-
void API_EXPORTED libusb_free_interface_association_descriptors(
|
|
1550
|
-
struct libusb_interface_association_descriptor_array *iad_array)
|
|
1551
|
-
{
|
|
1552
|
-
if (!iad_array)
|
|
1553
|
-
return;
|
|
1554
|
-
|
|
1555
|
-
if (iad_array->iad)
|
|
1556
|
-
free((void*)iad_array->iad);
|
|
1557
|
-
free(iad_array);
|
|
1558
|
-
}
|