source: mainline/uspace/app/usbinfo/info.c@ 8fdb18e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8fdb18e was b25199bc, checked in by Jan Vesely <jano.vesely@…>, 14 years ago

usbinfo: Check for available strings sooner and bail out if there are none.

  • Property mode set to 100644
File size: 11.9 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/dev/pipes.h>
40#include <usb/dev/recognise.h>
41#include <usb/dev/request.h>
42#include <usb/classes/classes.h>
43#include <usb/classes/hub.h>
44#include "usbinfo.h"
45
46void dump_short_device_identification(usbinfo_device_t *dev)
47{
48 printf("%sDevice 0x%04x by vendor 0x%04x\n", get_indent(0),
49 (int) dev->device_descriptor.product_id,
50 (int) dev->device_descriptor.vendor_id);
51}
52
53static void dump_match_ids_from_interface(
54 const uint8_t *descriptor, size_t depth, void *arg)
55{
56 if (depth != 1) {
57 return;
58 }
59 size_t descr_size = descriptor[0];
60 if (descr_size < sizeof(usb_standard_interface_descriptor_t)) {
61 return;
62 }
63 int descr_type = descriptor[1];
64 if (descr_type != USB_DESCTYPE_INTERFACE) {
65 return;
66 }
67
68 usbinfo_device_t *dev = (usbinfo_device_t *) arg;
69
70 usb_standard_interface_descriptor_t *iface
71 = (usb_standard_interface_descriptor_t *) descriptor;
72
73 printf("%sInterface #%d match ids (%s, 0x%02x, 0x%02x)\n",
74 get_indent(0),
75 (int) iface->interface_number,
76 usb_str_class(iface->interface_class),
77 (int) iface->interface_subclass,
78 (int) iface->interface_protocol);
79
80 match_id_list_t matches;
81 init_match_ids(&matches);
82 usb_device_create_match_ids_from_interface(&dev->device_descriptor,
83 iface, &matches);
84 dump_match_ids(&matches, get_indent(1));
85 clean_match_ids(&matches);
86}
87
88void dump_device_match_ids(usbinfo_device_t *dev)
89{
90 match_id_list_t matches;
91 init_match_ids(&matches);
92 usb_device_create_match_ids_from_device_descriptor(
93 &dev->device_descriptor, &matches);
94 printf("%sDevice match ids (0x%04x by 0x%04x, %s)\n", get_indent(0),
95 (int) dev->device_descriptor.product_id,
96 (int) dev->device_descriptor.vendor_id,
97 usb_str_class(dev->device_descriptor.device_class));
98 dump_match_ids(&matches, get_indent(1));
99 clean_match_ids(&matches);
100
101 usb_dp_walk_simple(dev->full_configuration_descriptor,
102 dev->full_configuration_descriptor_size,
103 usb_dp_standard_descriptor_nesting,
104 dump_match_ids_from_interface,
105 dev);
106}
107
108static void dump_descriptor_tree_brief_device(const char *prefix,
109 usb_standard_device_descriptor_t *descriptor)
110{
111 printf("%sDevice (0x%04x by 0x%04x, %s, %zu configurations)\n", prefix,
112 (int) descriptor->product_id,
113 (int) descriptor->vendor_id,
114 usb_str_class(descriptor->device_class),
115 (size_t) descriptor->configuration_count);
116}
117
118static void dump_descriptor_tree_brief_configuration(const char *prefix,
119 usb_standard_configuration_descriptor_t *descriptor)
120{
121 printf("%sConfiguration #%d (%zu interfaces, total %zuB)\n", prefix,
122 (int) descriptor->configuration_number,
123 (size_t) descriptor->interface_count,
124 (size_t) descriptor->total_length);
125}
126
127static void dump_descriptor_tree_brief_interface(const char *prefix,
128 usb_standard_interface_descriptor_t *descriptor)
129{
130 printf("%sInterface #%d (%s, 0x%02x, 0x%02x), alternate %d\n", prefix,
131 (int) descriptor->interface_number,
132 usb_str_class(descriptor->interface_class),
133 (int) descriptor->interface_subclass,
134 (int) descriptor->interface_protocol,
135 (int) descriptor->alternate_setting);
136}
137
138static void dump_descriptor_tree_brief_endpoint(const char *prefix,
139 usb_standard_endpoint_descriptor_t *descriptor)
140{
141 usb_endpoint_t endpoint_no = descriptor->endpoint_address & 0xF;
142 usb_transfer_type_t transfer = descriptor->attributes & 0x3;
143 usb_direction_t direction = descriptor->endpoint_address & 0x80
144 ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
145 printf("%sEndpoint #%d (%s %s, %zu)\n", prefix,
146 endpoint_no, usb_str_transfer_type(transfer),
147 direction == USB_DIRECTION_IN ? "in" : "out",
148 (size_t) descriptor->max_packet_size);
149}
150
151static void dump_descriptor_tree_brief_hid(const char *prefix,
152 usb_standard_hid_descriptor_t *descriptor)
153{
154 printf("%sHID (country %d, %d descriptors)\n", prefix,
155 (int) descriptor->country_code,
156 (int) descriptor->class_desc_count);
157}
158
159static void dump_descriptor_tree_brief_hub(const char *prefix,
160 usb_hub_descriptor_header_t *descriptor)
161{
162 printf("%shub (%d ports)\n", prefix,
163 (int) descriptor->port_count);
164}
165
166
167static void dump_descriptor_tree_callback(
168 const uint8_t *descriptor, size_t depth, void *arg)
169{
170 const char *indent = get_indent(depth + 1);
171
172 int descr_type = -1;
173 size_t descr_size = descriptor[0];
174 if (descr_size > 0) {
175 descr_type = descriptor[1];
176 }
177
178 switch (descr_type) {
179
180#define _BRANCH(type_enum, descriptor_type, callback) \
181 case type_enum: \
182 if (descr_size >= sizeof(descriptor_type)) { \
183 callback(indent, (descriptor_type *) descriptor); \
184 if (arg != NULL) { \
185 usb_dump_standard_descriptor(stdout, \
186 get_indent(depth +2), "\n", \
187 descriptor, descr_size); \
188 } \
189 } else { \
190 descr_type = -1; \
191 } \
192 break;
193
194 _BRANCH(USB_DESCTYPE_DEVICE,
195 usb_standard_device_descriptor_t,
196 dump_descriptor_tree_brief_device);
197 _BRANCH(USB_DESCTYPE_CONFIGURATION,
198 usb_standard_configuration_descriptor_t,
199 dump_descriptor_tree_brief_configuration);
200 _BRANCH(USB_DESCTYPE_INTERFACE,
201 usb_standard_interface_descriptor_t,
202 dump_descriptor_tree_brief_interface);
203 _BRANCH(USB_DESCTYPE_ENDPOINT,
204 usb_standard_endpoint_descriptor_t,
205 dump_descriptor_tree_brief_endpoint);
206 _BRANCH(USB_DESCTYPE_HID,
207 usb_standard_hid_descriptor_t,
208 dump_descriptor_tree_brief_hid);
209 /*
210 * Probably useless, hub descriptor shall not be part of
211 * configuration descriptor.
212 */
213 _BRANCH(USB_DESCTYPE_HUB,
214 usb_hub_descriptor_header_t,
215 dump_descriptor_tree_brief_hub);
216
217 default:
218 break;
219 }
220
221 if (descr_type == -1) {
222 printf("%sInvalid descriptor.\n", indent);
223 }
224}
225
226void dump_descriptor_tree_brief(usbinfo_device_t *dev)
227{
228 dump_descriptor_tree_callback((uint8_t *)&dev->device_descriptor,
229 (size_t) -1, NULL);
230 usb_dp_walk_simple(dev->full_configuration_descriptor,
231 dev->full_configuration_descriptor_size,
232 usb_dp_standard_descriptor_nesting,
233 dump_descriptor_tree_callback,
234 NULL);
235}
236
237void dump_descriptor_tree_full(usbinfo_device_t *dev)
238{
239 dump_descriptor_tree_callback((uint8_t *)&dev->device_descriptor,
240 (size_t) -1, dev);
241 usb_dp_walk_simple(dev->full_configuration_descriptor,
242 dev->full_configuration_descriptor_size,
243 usb_dp_standard_descriptor_nesting,
244 dump_descriptor_tree_callback,
245 dev);
246}
247
248static void find_string_indexes_callback(
249 const uint8_t *descriptor, size_t depth, void *arg)
250{
251 size_t descriptor_length = descriptor[0];
252 if (descriptor_length <= 1) {
253 return;
254 }
255
256 /*printf("Found string in %s->%s: %zu\n",
257 #descr_struct, #descr_item, __str_index); */
258#define SET_STRING_INDEX(descr, mask, descr_type, descr_struct, descr_item) \
259 do { \
260 if ((descr)[1] == (descr_type)) { \
261 descr_struct *__type_descr = (descr_struct *) (descr); \
262 size_t __str_index = __type_descr->descr_item; \
263 if ((__str_index > 0) && (__str_index < 64)) { \
264 mask = (mask) | (1 << __str_index); \
265 } \
266 } \
267 } while (0)
268
269 uint64_t *mask = arg;
270
271#define SET_STR(descr_type, descr_struct, descr_item) \
272 SET_STRING_INDEX(descriptor, (*mask), descr_type, descr_struct, descr_item)
273
274 SET_STR(USB_DESCTYPE_DEVICE, usb_standard_device_descriptor_t,
275 str_manufacturer);
276 SET_STR(USB_DESCTYPE_DEVICE, usb_standard_device_descriptor_t,
277 str_product);
278 SET_STR(USB_DESCTYPE_DEVICE, usb_standard_device_descriptor_t,
279 str_serial_number);
280 SET_STR(USB_DESCTYPE_CONFIGURATION, usb_standard_configuration_descriptor_t,
281 str_configuration);
282 SET_STR(USB_DESCTYPE_INTERFACE, usb_standard_interface_descriptor_t,
283 str_interface);
284}
285
286
287void dump_strings(usbinfo_device_t *dev)
288{
289 /* Find used indexes. Devices with more than 64 strings are very rare.*/
290 uint64_t str_mask = 0;
291 find_string_indexes_callback((uint8_t *)&dev->device_descriptor, 0,
292 &str_mask);
293 usb_dp_walk_simple(dev->full_configuration_descriptor,
294 dev->full_configuration_descriptor_size,
295 usb_dp_standard_descriptor_nesting,
296 find_string_indexes_callback,
297 &str_mask);
298
299 if (str_mask == 0) {
300 printf("Device does not support string descriptors.\n");
301 return;
302 }
303
304 /* Get supported languages. */
305 l18_win_locales_t *langs;
306 size_t langs_count;
307 int rc = usb_request_get_supported_languages(&dev->ctrl_pipe,
308 &langs, &langs_count);
309 if (rc != EOK) {
310 fprintf(stderr,
311 NAME ": failed to get list of supported languages: %s.\n",
312 str_error(rc));
313 return;
314 }
315
316 printf("%sString languages (%zu):", get_indent(0), langs_count);
317 size_t i;
318 for (i = 0; i < langs_count; i++) {
319 printf(" 0x%04x", (int) langs[i]);
320 }
321 printf(".\n");
322
323 /* Get all strings and dump them. */
324 for (i = 0; i < langs_count; i++) {
325 l18_win_locales_t lang = langs[i];
326
327 printf("%sStrings in %s:\n", get_indent(0),
328 str_l18_win_locale(lang));
329
330 size_t idx;
331 for (idx = 1; idx < 64; idx++) {
332 if ((str_mask & ((uint64_t)1 << idx)) == 0) {
333 continue;
334 }
335 char *string = NULL;
336 rc = usb_request_get_string(&dev->ctrl_pipe, idx, lang,
337 &string);
338 if ((rc != EOK) && (rc != EEMPTY)) {
339 printf("%sWarn: failed to retrieve string #%zu: %s.\n",
340 get_indent(1), idx, str_error(rc));
341 continue;
342 }
343 printf("%sString #%zu: \"%s\"\n", get_indent(1),
344 idx, rc == EOK ? string : "");
345 if (string != NULL) {
346 free(string);
347 }
348 }
349 }
350}
351
352
353void dump_status(usbinfo_device_t *dev)
354{
355 int rc;
356 uint16_t device_status = 0;
357 uint16_t ctrl_pipe_status = 0;
358
359 /* Device status first. */
360 rc = usb_request_get_status(&dev->ctrl_pipe,
361 USB_REQUEST_RECIPIENT_DEVICE, 0,
362 &device_status);
363 if (rc != EOK) {
364 printf("%sFailed to get device status: %s.\n",
365 get_indent(0), str_error(rc));
366 goto try_ctrl_pipe_status;
367 }
368
369 printf("%sDevice status 0x%04x: power=%s, remote-wakeup=%s.\n",
370 get_indent(0),
371 device_status,
372 device_status & USB_DEVICE_STATUS_SELF_POWERED ? "self" : "bus",
373 device_status & USB_DEVICE_STATUS_REMOTE_WAKEUP ? "yes" : "no");
374
375 /* Interface is not interesting, skipping ;-). */
376
377 /* Control endpoint zero. */
378try_ctrl_pipe_status:
379 rc = usb_request_get_status(&dev->ctrl_pipe,
380 USB_REQUEST_RECIPIENT_ENDPOINT, 0,
381 &ctrl_pipe_status);
382 if (rc != EOK) {
383 printf("%sFailed to get control endpoint status: %s.\n",
384 get_indent(0), str_error(rc));
385 goto leave;
386 }
387
388 printf("%sControl endpoint zero status %04X: halted=%s.\n",
389 get_indent(0),
390 ctrl_pipe_status,
391 ctrl_pipe_status & USB_ENDPOINT_STATUS_HALTED ? "yes" : "no");
392
393leave:
394 return;
395}
396
397/** @}
398 */
Note: See TracBrowser for help on using the repository browser.