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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5608106c was e8975278, checked in by Jiri Svoboda <jiri@…>, 7 years ago

A few more cstyle fixes.

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