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

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

usbinfo prints device status as well

Device (and control endpoint zero) status is printed via `-S' switch.

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