source: mainline/uspace/app/usbinfo/info.c@ da77278

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

Add printing of descriptor tree to usbinfo

  • Property mode set to 100644
File size: 9.0 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
52void dump_device_match_ids(usbinfo_device_t *dev)
53{
54 match_id_list_t matches;
55 init_match_ids(&matches);
56 usb_device_create_match_ids_from_device_descriptor(
57 &dev->device_descriptor, &matches);
58 dump_match_ids(&matches, get_indent(0));
59}
60
61static void dump_descriptor_tree_brief_device(const char *prefix,
62 usb_standard_device_descriptor_t *descriptor)
63{
64 printf("%sDevice (0x%04x by 0x%04x, %s)\n", prefix,
65 (int) descriptor->product_id,
66 (int) descriptor->vendor_id,
67 usb_str_class(descriptor->device_class));
68}
69
70static void dump_descriptor_tree_brief_configuration(const char *prefix,
71 usb_standard_configuration_descriptor_t *descriptor)
72{
73 printf("%sConfiguration #%d\n", prefix,
74 (int) descriptor->configuration_number);
75}
76
77static void dump_descriptor_tree_brief_interface(const char *prefix,
78 usb_standard_interface_descriptor_t *descriptor)
79{
80 printf("%sInterface #%d (%s, 0x%02x, 0x%02x)\n", prefix,
81 (int) descriptor->interface_number,
82 usb_str_class(descriptor->interface_class),
83 (int) descriptor->interface_subclass,
84 (int) descriptor->interface_protocol);
85}
86
87static void dump_descriptor_tree_brief_endpoint(const char *prefix,
88 usb_standard_endpoint_descriptor_t *descriptor)
89{
90 usb_endpoint_t endpoint_no = descriptor->endpoint_address & 0xF;
91 usb_transfer_type_t transfer = descriptor->attributes & 0x3;
92 usb_direction_t direction = descriptor->endpoint_address & 0x80
93 ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
94 printf("%sEndpoint #%d (%s %s, %zu)\n", prefix,
95 endpoint_no, usb_str_transfer_type(transfer),
96 direction == USB_DIRECTION_IN ? "in" : "out",
97 (size_t) descriptor->max_packet_size);
98}
99
100
101static void dump_descriptor_tree_brief_callback(uint8_t *descriptor,
102 size_t depth, void *arg)
103{
104 const char *indent = get_indent(depth);
105
106 int descr_type = -1;
107 size_t descr_size = descriptor[0];
108 if (descr_size > 0) {
109 descr_type = descriptor[1];
110 }
111
112 switch (descr_type) {
113
114#define _BRANCH(type_enum, descriptor_type, callback) \
115 case type_enum: \
116 if (descr_size >= sizeof(descriptor_type)) { \
117 callback(indent, (descriptor_type *) descriptor); \
118 } else { \
119 descr_type = -1; \
120 } \
121 break;
122
123 _BRANCH(USB_DESCTYPE_DEVICE,
124 usb_standard_device_descriptor_t,
125 dump_descriptor_tree_brief_device);
126 _BRANCH(USB_DESCTYPE_CONFIGURATION,
127 usb_standard_configuration_descriptor_t,
128 dump_descriptor_tree_brief_configuration);
129 _BRANCH(USB_DESCTYPE_INTERFACE,
130 usb_standard_interface_descriptor_t,
131 dump_descriptor_tree_brief_interface);
132 _BRANCH(USB_DESCTYPE_ENDPOINT,
133 usb_standard_endpoint_descriptor_t,
134 dump_descriptor_tree_brief_endpoint);
135
136 default:
137 break;
138 }
139
140 if (descr_type == -1) {
141 printf("%sInvalid descriptor.\n", indent);
142 }
143}
144
145void dump_descriptor_tree_brief(usbinfo_device_t *dev)
146{
147 dump_descriptor_tree_brief_callback((uint8_t *)&dev->device_descriptor,
148 0, NULL);
149 browse_descriptor_tree(dev->full_configuration_descriptor,
150 dev->full_configuration_descriptor_size,
151 usb_dp_standard_descriptor_nesting,
152 dump_descriptor_tree_brief_callback,
153 1,
154 NULL);
155}
156
157int dump_device(devman_handle_t hc_handle, usb_address_t address)
158{
159 int rc;
160 usb_device_connection_t wire;
161 usb_endpoint_pipe_t ctrl_pipe;
162
163 /*
164 * Initialize pipes.
165 */
166 rc = usb_device_connection_initialize(&wire, hc_handle, address);
167 if (rc != EOK) {
168 fprintf(stderr,
169 NAME ": failed to create connection to the device: %s.\n",
170 str_error(rc));
171 goto leave;
172 }
173 rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe, &wire);
174 if (rc != EOK) {
175 fprintf(stderr,
176 NAME ": failed to create default control pipe: %s.\n",
177 str_error(rc));
178 goto leave;
179 }
180 rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);
181 if (rc != EOK) {
182 fprintf(stderr,
183 NAME ": probing default control pipe failed: %s.\n",
184 str_error(rc));
185 goto leave;
186 }
187 rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
188 if (rc != EOK) {
189 fprintf(stderr,
190 NAME ": failed to start session on control pipe: %s.\n",
191 str_error(rc));
192 goto leave;
193 }
194
195 /*
196 * Dump information about possible match ids.
197 */
198 match_id_list_t match_id_list;
199 init_match_ids(&match_id_list);
200 rc = usb_device_create_match_ids(&ctrl_pipe, &match_id_list);
201 if (rc != EOK) {
202 fprintf(stderr,
203 NAME ": failed to fetch match ids of the device: %s.\n",
204 str_error(rc));
205 goto leave;
206 }
207 dump_match_ids(&match_id_list, get_indent(0));
208
209 /*
210 * Get device descriptor and dump it.
211 */
212 usb_standard_device_descriptor_t device_descriptor;
213 rc = usb_request_get_device_descriptor(&ctrl_pipe, &device_descriptor);
214 if (rc != EOK) {
215 fprintf(stderr,
216 NAME ": failed to fetch standard device descriptor: %s.\n",
217 str_error(rc));
218 goto leave;
219 }
220 dump_usb_descriptor((uint8_t *)&device_descriptor, sizeof(device_descriptor));
221
222 rc = EOK;
223 goto leave;
224
225 /*
226 * Get first configuration descriptor and dump it.
227 */
228 usb_standard_configuration_descriptor_t config_descriptor;
229 int config_index = 0;
230 rc = usb_request_get_bare_configuration_descriptor(&ctrl_pipe,
231 config_index, &config_descriptor);
232 if (rc != EOK) {
233 fprintf(stderr,
234 NAME ": failed to fetch standard configuration descriptor: %s.\n",
235 str_error(rc));
236 goto leave;
237 }
238 //dump_standard_configuration_descriptor(config_index, &config_descriptor);
239
240 void *full_config_descriptor = malloc(config_descriptor.total_length);
241 rc = usb_request_get_full_configuration_descriptor(&ctrl_pipe,
242 config_index,
243 full_config_descriptor, config_descriptor.total_length, NULL);
244 if (rc != EOK) {
245 fprintf(stderr,
246 NAME ": failed to fetch full configuration descriptor: %s.\n",
247 str_error(rc));
248 goto leave;
249 }
250
251 dump_descriptor_tree(full_config_descriptor,
252 config_descriptor.total_length);
253
254 /*
255 * Get supported languages of STRING descriptors.
256 */
257 l18_win_locales_t *langs;
258 size_t langs_count;
259 rc = usb_request_get_supported_languages(&ctrl_pipe,
260 &langs, &langs_count);
261 if (rc != EOK) {
262 fprintf(stderr,
263 NAME ": failed to get list of supported languages: %s.\n",
264 str_error(rc));
265 goto skip_strings;
266 }
267
268 printf("String languages (%zu):", langs_count);
269 size_t i;
270 for (i = 0; i < langs_count; i++) {
271 printf(" 0x%04x", (int) langs[i]);
272 }
273 printf(".\n");
274
275 /*
276 * Dump all strings in all available langages;
277 */
278 for (i = 0; i < langs_count; i++) {
279 l18_win_locales_t lang = langs[i];
280
281 printf("%sStrings for language 0x%04x:\n", get_indent(0),
282 (int) lang);
283
284 /*
285 * Try all indexes - we will see what pops-up ;-).
286 * However, to speed things up, we will stop after
287 * encountering several broken (or nonexistent ones)
288 * descriptors in line.
289 */
290 size_t idx;
291 size_t failed_count = 0;
292 for (idx = 1; idx < 0xFF; idx++) {
293 char *string;
294 rc = usb_request_get_string(&ctrl_pipe, idx, lang,
295 &string);
296 if (rc != EOK) {
297 failed_count++;
298 if (failed_count > 3) {
299 break;
300 }
301 continue;
302 }
303 printf("%sString #%zu: \"%s\"\n", get_indent(1),
304 idx, string);
305 free(string);
306 failed_count = 0; /* Reset failed counter. */
307 }
308 }
309
310
311skip_strings:
312
313 rc = EOK;
314
315leave:
316 /* Ignoring errors here. */
317 usb_endpoint_pipe_end_session(&ctrl_pipe);
318
319 return rc;
320}
321
322/** @}
323 */
Note: See TracBrowser for help on using the repository browser.