source: mainline/uspace/app/usbinfo/info.c@ 7b13d8e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7b13d8e was 7b13d8e, checked in by Vojtech Horky <vojtechhorky@…>, 15 years ago

usbinfo prints match ids from interfaces too

  • Property mode set to 100644
File size: 10.4 KB
Line 
1/*
2 * Copyright (c) 2011 Vojtech Horky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup usbinfo
30 * @{
31 */
32/**
33 * @file
34 * Dumping of generic device properties.
35 */
36#include <stdio.h>
37#include <str_error.h>
38#include <errno.h>
39#include <usb/pipes.h>
40#include <usb/recognise.h>
41#include <usb/request.h>
42#include <usb/classes/classes.h>
43#include "usbinfo.h"
44
45void dump_short_device_identification(usbinfo_device_t *dev)
46{
47 printf("%sDevice 0x%04x by vendor 0x%04x\n", get_indent(0),
48 (int) dev->device_descriptor.product_id,
49 (int) dev->device_descriptor.vendor_id);
50}
51
52static void dump_match_ids_from_interface(uint8_t *descriptor, size_t depth,
53 void *arg)
54{
55 if (depth != 1) {
56 return;
57 }
58 size_t descr_size = descriptor[0];
59 if (descr_size < sizeof(usb_standard_interface_descriptor_t)) {
60 return;
61 }
62 int descr_type = descriptor[1];
63 if (descr_type != USB_DESCTYPE_INTERFACE) {
64 return;
65 }
66
67 usbinfo_device_t *dev = (usbinfo_device_t *) arg;
68
69 usb_standard_interface_descriptor_t *iface
70 = (usb_standard_interface_descriptor_t *) descriptor;
71
72 printf("%sInterface #%d match ids (%s, 0x%02x, 0x%02x)\n",
73 get_indent(0),
74 (int) iface->interface_number,
75 usb_str_class(iface->interface_class),
76 (int) iface->interface_subclass,
77 (int) iface->interface_protocol);
78
79 match_id_list_t matches;
80 init_match_ids(&matches);
81 usb_device_create_match_ids_from_interface(&dev->device_descriptor,
82 iface, &matches);
83 dump_match_ids(&matches, get_indent(1));
84 clean_match_ids(&matches);
85}
86
87void dump_device_match_ids(usbinfo_device_t *dev)
88{
89 match_id_list_t matches;
90 init_match_ids(&matches);
91 usb_device_create_match_ids_from_device_descriptor(
92 &dev->device_descriptor, &matches);
93 printf("%sDevice match ids (0x%04x by 0x%04x, %s)\n", get_indent(0),
94 (int) dev->device_descriptor.product_id,
95 (int) dev->device_descriptor.vendor_id,
96 usb_str_class(dev->device_descriptor.device_class));
97 dump_match_ids(&matches, get_indent(1));
98 clean_match_ids(&matches);
99
100 usb_dp_walk_simple(dev->full_configuration_descriptor,
101 dev->full_configuration_descriptor_size,
102 usb_dp_standard_descriptor_nesting,
103 dump_match_ids_from_interface,
104 dev);
105}
106
107static void dump_descriptor_tree_brief_device(const char *prefix,
108 usb_standard_device_descriptor_t *descriptor)
109{
110 printf("%sDevice (0x%04x by 0x%04x, %s)\n", prefix,
111 (int) descriptor->product_id,
112 (int) descriptor->vendor_id,
113 usb_str_class(descriptor->device_class));
114}
115
116static void dump_descriptor_tree_brief_configuration(const char *prefix,
117 usb_standard_configuration_descriptor_t *descriptor)
118{
119 printf("%sConfiguration #%d\n", prefix,
120 (int) descriptor->configuration_number);
121}
122
123static void dump_descriptor_tree_brief_interface(const char *prefix,
124 usb_standard_interface_descriptor_t *descriptor)
125{
126 printf("%sInterface #%d (%s, 0x%02x, 0x%02x)\n", prefix,
127 (int) descriptor->interface_number,
128 usb_str_class(descriptor->interface_class),
129 (int) descriptor->interface_subclass,
130 (int) descriptor->interface_protocol);
131}
132
133static void dump_descriptor_tree_brief_endpoint(const char *prefix,
134 usb_standard_endpoint_descriptor_t *descriptor)
135{
136 usb_endpoint_t endpoint_no = descriptor->endpoint_address & 0xF;
137 usb_transfer_type_t transfer = descriptor->attributes & 0x3;
138 usb_direction_t direction = descriptor->endpoint_address & 0x80
139 ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
140 printf("%sEndpoint #%d (%s %s, %zu)\n", prefix,
141 endpoint_no, usb_str_transfer_type(transfer),
142 direction == USB_DIRECTION_IN ? "in" : "out",
143 (size_t) descriptor->max_packet_size);
144}
145
146
147static void dump_descriptor_tree_brief_callback(uint8_t *descriptor,
148 size_t depth, void *arg)
149{
150 const char *indent = get_indent(depth + 1);
151
152 int descr_type = -1;
153 size_t descr_size = descriptor[0];
154 if (descr_size > 0) {
155 descr_type = descriptor[1];
156 }
157
158 switch (descr_type) {
159
160#define _BRANCH(type_enum, descriptor_type, callback) \
161 case type_enum: \
162 if (descr_size >= sizeof(descriptor_type)) { \
163 callback(indent, (descriptor_type *) descriptor); \
164 } else { \
165 descr_type = -1; \
166 } \
167 break;
168
169 _BRANCH(USB_DESCTYPE_DEVICE,
170 usb_standard_device_descriptor_t,
171 dump_descriptor_tree_brief_device);
172 _BRANCH(USB_DESCTYPE_CONFIGURATION,
173 usb_standard_configuration_descriptor_t,
174 dump_descriptor_tree_brief_configuration);
175 _BRANCH(USB_DESCTYPE_INTERFACE,
176 usb_standard_interface_descriptor_t,
177 dump_descriptor_tree_brief_interface);
178 _BRANCH(USB_DESCTYPE_ENDPOINT,
179 usb_standard_endpoint_descriptor_t,
180 dump_descriptor_tree_brief_endpoint);
181
182 default:
183 break;
184 }
185
186 if (descr_type == -1) {
187 printf("%sInvalid descriptor.\n", indent);
188 }
189}
190
191void dump_descriptor_tree_brief(usbinfo_device_t *dev)
192{
193 dump_descriptor_tree_brief_callback((uint8_t *)&dev->device_descriptor,
194 (size_t) -1, NULL);
195 usb_dp_walk_simple(dev->full_configuration_descriptor,
196 dev->full_configuration_descriptor_size,
197 usb_dp_standard_descriptor_nesting,
198 dump_descriptor_tree_brief_callback,
199 NULL);
200}
201
202int dump_device(devman_handle_t hc_handle, usb_address_t address)
203{
204 int rc;
205 usb_device_connection_t wire;
206 usb_endpoint_pipe_t ctrl_pipe;
207
208 /*
209 * Initialize pipes.
210 */
211 rc = usb_device_connection_initialize(&wire, hc_handle, address);
212 if (rc != EOK) {
213 fprintf(stderr,
214 NAME ": failed to create connection to the device: %s.\n",
215 str_error(rc));
216 goto leave;
217 }
218 rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe, &wire);
219 if (rc != EOK) {
220 fprintf(stderr,
221 NAME ": failed to create default control pipe: %s.\n",
222 str_error(rc));
223 goto leave;
224 }
225 rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);
226 if (rc != EOK) {
227 fprintf(stderr,
228 NAME ": probing default control pipe failed: %s.\n",
229 str_error(rc));
230 goto leave;
231 }
232 rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
233 if (rc != EOK) {
234 fprintf(stderr,
235 NAME ": failed to start session on control pipe: %s.\n",
236 str_error(rc));
237 goto leave;
238 }
239
240 /*
241 * Dump information about possible match ids.
242 */
243 match_id_list_t match_id_list;
244 init_match_ids(&match_id_list);
245 rc = usb_device_create_match_ids(&ctrl_pipe, &match_id_list);
246 if (rc != EOK) {
247 fprintf(stderr,
248 NAME ": failed to fetch match ids of the device: %s.\n",
249 str_error(rc));
250 goto leave;
251 }
252 dump_match_ids(&match_id_list, get_indent(0));
253
254 /*
255 * Get device descriptor and dump it.
256 */
257 usb_standard_device_descriptor_t device_descriptor;
258 rc = usb_request_get_device_descriptor(&ctrl_pipe, &device_descriptor);
259 if (rc != EOK) {
260 fprintf(stderr,
261 NAME ": failed to fetch standard device descriptor: %s.\n",
262 str_error(rc));
263 goto leave;
264 }
265 dump_usb_descriptor((uint8_t *)&device_descriptor, sizeof(device_descriptor));
266
267 rc = EOK;
268 goto leave;
269
270 /*
271 * Get first configuration descriptor and dump it.
272 */
273 usb_standard_configuration_descriptor_t config_descriptor;
274 int config_index = 0;
275 rc = usb_request_get_bare_configuration_descriptor(&ctrl_pipe,
276 config_index, &config_descriptor);
277 if (rc != EOK) {
278 fprintf(stderr,
279 NAME ": failed to fetch standard configuration descriptor: %s.\n",
280 str_error(rc));
281 goto leave;
282 }
283 //dump_standard_configuration_descriptor(config_index, &config_descriptor);
284
285 void *full_config_descriptor = malloc(config_descriptor.total_length);
286 rc = usb_request_get_full_configuration_descriptor(&ctrl_pipe,
287 config_index,
288 full_config_descriptor, config_descriptor.total_length, NULL);
289 if (rc != EOK) {
290 fprintf(stderr,
291 NAME ": failed to fetch full configuration descriptor: %s.\n",
292 str_error(rc));
293 goto leave;
294 }
295
296 dump_descriptor_tree(full_config_descriptor,
297 config_descriptor.total_length);
298
299 /*
300 * Get supported languages of STRING descriptors.
301 */
302 l18_win_locales_t *langs;
303 size_t langs_count;
304 rc = usb_request_get_supported_languages(&ctrl_pipe,
305 &langs, &langs_count);
306 if (rc != EOK) {
307 fprintf(stderr,
308 NAME ": failed to get list of supported languages: %s.\n",
309 str_error(rc));
310 goto skip_strings;
311 }
312
313 printf("String languages (%zu):", langs_count);
314 size_t i;
315 for (i = 0; i < langs_count; i++) {
316 printf(" 0x%04x", (int) langs[i]);
317 }
318 printf(".\n");
319
320 /*
321 * Dump all strings in all available langages;
322 */
323 for (i = 0; i < langs_count; i++) {
324 l18_win_locales_t lang = langs[i];
325
326 printf("%sStrings for language 0x%04x:\n", get_indent(0),
327 (int) lang);
328
329 /*
330 * Try all indexes - we will see what pops-up ;-).
331 * However, to speed things up, we will stop after
332 * encountering several broken (or nonexistent ones)
333 * descriptors in line.
334 */
335 size_t idx;
336 size_t failed_count = 0;
337 for (idx = 1; idx < 0xFF; idx++) {
338 char *string;
339 rc = usb_request_get_string(&ctrl_pipe, idx, lang,
340 &string);
341 if (rc != EOK) {
342 failed_count++;
343 if (failed_count > 3) {
344 break;
345 }
346 continue;
347 }
348 printf("%sString #%zu: \"%s\"\n", get_indent(1),
349 idx, string);
350 free(string);
351 failed_count = 0; /* Reset failed counter. */
352 }
353 }
354
355
356skip_strings:
357
358 rc = EOK;
359
360leave:
361 /* Ignoring errors here. */
362 usb_endpoint_pipe_end_session(&ctrl_pipe);
363
364 return rc;
365}
366
367/** @}
368 */
Note: See TracBrowser for help on using the repository browser.